summaryrefslogtreecommitdiff
path: root/rust/zerocopy/src/pointer
diff options
context:
space:
mode:
authorMiguel Ojeda <ojeda@kernel.org>2026-10-13 20:48:08 +0200
committerMiguel Ojeda <ojeda@kernel.org>2026-10-15 09:14:38 +0200
commit7c306f00835a237a70024a8f968dbc3bc8db8fcf (patch)
tree4d7e2bfc5a7f69bb51d05dea6295a122c7295254 /rust/zerocopy/src/pointer
parentd61be5c960e4b89b2e6fa8cedc1d9aa64401ae13 (diff)
downloadlinux-next-7c306f00835a237a70024a8f968dbc3bc8db8fcf.tar.gz
linux-next-7c306f00835a237a70024a8f968dbc3bc8db8fcf.zip
rust: zerocopy: update to v0.8.62
Update our vendored copy of `zerocopy` (and `zerocopy-derive`) to v0.8.62. This update advances 8 releases, with 3 of them carrying most of the changes. It contains new features as well as fixes [1]. However, almost nothing has changed that requires updates on our side: we only need to move our non-ASCII change to the recently added `project.rs` file, and to add an SPDX license identifier to the also new `invariant.rs` file (I reported it to upstream [2]). The following script may be used to check for the remaining differences: for path in $(cd rust/zerocopy-derive/ && find . -type f ! -name README.md); do curl --silent --show-error --location \ https://github.com/google/zerocopy/raw/v0.8.62/zerocopy/zerocopy-derive/src/$path | git diff --no-index - rust/zerocopy-derive/$path && echo $path: OK done for path in $(cd rust/zerocopy/ && find . -type f ! -name README.md); do curl --silent --show-error --location \ https://github.com/google/zerocopy/raw/v0.8.62/zerocopy/$path | git diff --no-index - rust/zerocopy/$path && echo $path: OK done Comparing the output above with the one for the latest update (v0.8.54) shows no new differences on our side apart from the two mentioned above. Cc: Joshua Liebow-Feeser <joshlf@google.com> Cc: Jack Wrenn <jswrenn@google.com> Link: https://github.com/google/zerocopy/releases [1] Link: https://github.com/google/zerocopy/issues/3858 [2] Assisted-by: LLM Reviewed-by: Alice Ryhl <aliceryhl@google.com> Link: https://patch.msgid.link/20261013184809.35143-2-ojeda@kernel.org Signed-off-by: Miguel Ojeda <ojeda@kernel.org>
Diffstat (limited to 'rust/zerocopy/src/pointer')
-rw-r--r--rust/zerocopy/src/pointer/inner.rs35
-rw-r--r--rust/zerocopy/src/pointer/invariant.rs61
-rw-r--r--rust/zerocopy/src/pointer/mod.rs50
-rw-r--r--rust/zerocopy/src/pointer/ptr.rs177
-rw-r--r--rust/zerocopy/src/pointer/transmute.rs100
5 files changed, 245 insertions, 178 deletions
diff --git a/rust/zerocopy/src/pointer/inner.rs b/rust/zerocopy/src/pointer/inner.rs
index 949b60a3f83e..8beb6267b217 100644
--- a/rust/zerocopy/src/pointer/inner.rs
+++ b/rust/zerocopy/src/pointer/inner.rs
@@ -289,10 +289,10 @@ where
///
/// Given `let (left, right) = ptr.split_at(l_len)`, it is guaranteed that
/// `left` and `right` are contiguous and non-overlapping if
- /// `l_len.padding_needed_for() == 0`. This is true for all `[T]`.
+ /// the left part has no trailing padding. This is true for all `[T]`.
///
- /// If `l_len.padding_needed_for() != 0`, then the left pointer will overlap
- /// the right pointer to satisfy `T`'s padding requirements.
+ /// Any trailing padding in the left part begins at the right part's
+ /// starting address and may overlap its referent.
#[inline]
#[must_use]
pub unsafe fn split_at_unchecked(
@@ -313,23 +313,19 @@ where
// Trivially, `slf.meta() <= slf.meta()`.
let right = unsafe { right.slice_unchecked(l_len..self.meta().get()) };
- // SAFETY: If `l_len.padding_needed_for() == 0`, then `left` and `right`
- // are non-overlapping. Proof: `left` is constructed `slf` with `l_len`
- // as its (exclusive) upper bound. If `l_len.padding_needed_for() == 0`,
- // then `left` requires no trailing padding following its final element.
- // Since `right` is constructed from `slf`'s trailing slice with `l_len`
- // as its (inclusive) lower bound, no byte is referred to by both
- // pointers.
+ // SAFETY: If the left part has no trailing padding, then `left` and
+ // `right` are non-overlapping. Proof: `left` has `l_len` trailing
+ // elements, and `right` starts at element `l_len` of the original
+ // trailing slice. Without padding after `left`'s final element, no
+ // byte is referred to by both pointers.
//
- // Conversely, `l_len.padding_needed_for() == N`, where `N
- // > 0`, `left` requires `N` bytes of trailing padding following its
- // final element. Since `right` is constructed from the trailing slice
- // of `slf` with `l_len` as its (inclusive) lower bound, the first `N`
- // bytes of `right` are aliased by `left`.
+ // Any trailing padding in `left` begins at `right`'s starting
+ // address. If `right` is nonzero sized, the referents overlap.
(left, right)
}
- /// Produces the trailing slice of `self`.
+ /// Produces the trailing slice of `self` using `T::Elem` as its element
+ /// representation.
#[inline]
#[must_use]
pub fn trailing_slice(self) -> PtrInner<'a, [T::Elem]>
@@ -368,9 +364,10 @@ where
// 1. If `ptr`'s referent is not zero sized, then `ptr` has valid
// provenance for `A` because `raw` is derived from the same
// allocated object as `self` via provenance-preserving operations.
- // 2. If `ptr`'s referent is not zero sized, then `ptr` addresses a byte
- // range which is entirely contained in `A`, by previous safety proof
- // on `bytes`.
+ // 2. `T: SplitAt` guarantees that `T::Elem` has the size of the actual
+ // trailing element. The new slice has the same length and start as
+ // the original trailing slice, so it covers the same byte range.
+ // If nonzero sized, that range is entirely contained in `A`.
// 3. `ptr` addresses a byte range whose length fits in an `isize`, by
// consequence of #2.
// 4. `ptr` addresses a byte range which does not wrap around the
diff --git a/rust/zerocopy/src/pointer/invariant.rs b/rust/zerocopy/src/pointer/invariant.rs
index 7ff0d43dad5e..8dfaf82e134f 100644
--- a/rust/zerocopy/src/pointer/invariant.rs
+++ b/rust/zerocopy/src/pointer/invariant.rs
@@ -47,7 +47,7 @@ pub trait Alignment: Sealed {
fn read<T, I, R>(ptr: crate::Ptr<'_, T, I>) -> T
where
T: Copy + Read<I::Aliasing, R>,
- I: Invariants<Alignment = Self, Validity = Valid>,
+ I: Invariants<Alignment = Self, Validity = Safe>,
I::Aliasing: Reference;
}
@@ -64,35 +64,39 @@ pub trait Alignment: Sealed {
/// all `T: ?Sized`. Any `V: Validity` must guarantee that this set is only a
/// function of the *bit validity* of the referent type, `T`, and not of any
/// other property of `T`. As a consequence, given `V: Validity`, `T`, and `U`
-/// where `T` and `U` have the same bit validity, `S(V, T) = S(V, U)`.
+/// where `T` and `U` have the same bit validity, `S(T, V) = S(U, V)`.
///
/// It is guaranteed that the referent of any `ptr: Ptr<T, V>` is a member of
/// `S(T, V)`. Unsafe code must ensure that this guarantee will be upheld for
/// any existing `Ptr`s or any `Ptr`s that that code creates.
///
-/// An important implication of this guarantee is that it restricts what
-/// transmutes are sound, where "transmute" is used in this context to refer to
-/// changing the referent type or validity invariant of a `Ptr`, as either
-/// change may change the set of bit values permitted to appear in the referent.
-/// In particular, the following are necessary (but not sufficient) conditions
-/// in order for a transmute from `src: Ptr<T, V>` to `dst: Ptr<U, W>` to be
-/// sound:
-/// - If `S(T, V) = S(U, W)`, then no restrictions apply; otherwise,
+/// An important implication of this guarantee is that it restricts which exact
+/// reinterpretations are sound. Here, an exact reinterpretation changes the
+/// referent type or validity invariant of a `Ptr` while preserving the exact
+/// byte range. In particular, given `src: Ptr<T, V>` and `dst: Ptr<U, W>` which
+/// refer to the same byte range, the following are necessary (but not
+/// sufficient) conditions:
+/// - If `S(T, V) = S(U, W)`, then no additional validity-preservation
+/// restrictions apply; otherwise,
/// - If `dst` permits mutation of its referent (e.g. via `Exclusive` aliasing
/// or interior mutation under `Shared` aliasing), then it must hold that
-/// `S(T, V) ⊇ S(U, W)` - in other words, the transmute must not expand the
-/// set of allowed referent bit patterns. A violation of this requirement
+/// `S(T, V) ⊇ S(U, W)` - in other words, the reinterpretation must not expand
+/// the set of allowed referent bit patterns. A violation of this requirement
/// would permit using `dst` to write `x` where `x ∈ S(U, W)` but `x ∉ S(T,
/// V)`, which would violate the guarantee that `src`'s referent may only
/// contain values in `S(T, V)`.
/// - If the referent may be mutated without going through `dst` while `dst` is
/// live (e.g. via interior mutation on a `Shared`-aliased `Ptr` or `&`
/// reference), then it must hold that `S(T, V) ⊆ S(U, W)` - in other words,
-/// the transmute must not shrink the set of allowed referent bit patterns. A
-/// violation of this requirement would permit using `src` or another
-/// mechanism (e.g. a `&` reference used to derive `src`) to write `x` where
-/// `x ∈ S(T, V)` but `x ∉ S(U, W)`, which would violate the guarantee that
-/// `dst`'s referent may only contain values in `S(U, W)`.
+/// the reinterpretation must not shrink the set of allowed referent bit
+/// patterns. A violation of this requirement would permit using `src` or
+/// another mechanism (e.g. a `&` reference used to derive `src`) to write `x`
+/// where `x ∈ S(T, V)` but `x ∉ S(U, W)`, which would violate the guarantee
+/// that `dst`'s referent may only contain values in `S(U, W)`.
+///
+/// These conditions describe only exact reinterpretations. Shrinking
+/// projections may have validity that depends on the relationship between the
+/// projected region and bytes outside it, and require additional reasoning.
pub unsafe trait Validity: Sealed {
const KIND: ValidityKind;
}
@@ -101,7 +105,7 @@ pub enum ValidityKind {
Uninit,
AsInitialized,
Initialized,
- Valid,
+ Safe,
}
/// An [`Aliasing`] invariant which is either [`Shared`] or [`Exclusive`].
@@ -147,7 +151,7 @@ impl Alignment for Unaligned {
fn read<T, I, R>(ptr: crate::Ptr<'_, T, I>) -> T
where
T: Copy + Read<I::Aliasing, R>,
- I: Invariants<Alignment = Self, Validity = Valid>,
+ I: Invariants<Alignment = Self, Validity = Safe>,
I::Aliasing: Reference,
{
(*ptr.into_unalign().as_ref()).into_inner()
@@ -162,7 +166,7 @@ impl Alignment for Aligned {
fn read<T, I, R>(ptr: crate::Ptr<'_, T, I>) -> T
where
T: Copy + Read<I::Aliasing, R>,
- I: Invariants<Alignment = Self, Validity = Valid>,
+ I: Invariants<Alignment = Self, Validity = Safe>,
I::Aliasing: Reference,
{
*ptr.as_ref()
@@ -227,13 +231,20 @@ unsafe impl Validity for Initialized {
/// The referent of a `Ptr<T>` is valid for `T`, upholding bit validity and any
/// library safety invariants.
-pub enum Valid {}
-// SAFETY: `Valid`'s validity is well-defined for all `T: ?Sized`, and is not a
+pub enum Safe {}
+// SAFETY: `Safe`'s validity is well-defined for all `T: ?Sized`, and is not a
// function of any property of `T` other than its bit validity.
-unsafe impl Validity for Valid {
- const KIND: ValidityKind = ValidityKind::Valid;
+unsafe impl Validity for Safe {
+ const KIND: ValidityKind = ValidityKind::Safe;
}
+/// Proof helper for casts whose validity requirement does not depend on the
+/// referent type.
+///
+/// Currently this covers `Uninit`, which permits any byte state, and
+/// `Initialized`, which requires every referent byte to be initialized
+/// regardless of referent type.
+///
/// # Safety
///
/// `DT: CastableFrom<ST, SV, DV>` is sound if `SV = DV = Uninit` or `SV = DV =
@@ -289,7 +300,7 @@ mod sealed {
impl Sealed for Uninit {}
impl Sealed for AsInitialized {}
impl Sealed for Initialized {}
- impl Sealed for Valid {}
+ impl Sealed for Safe {}
impl<A: Sealed, AA: Sealed, V: Sealed> Sealed for (A, AA, V) {}
diff --git a/rust/zerocopy/src/pointer/mod.rs b/rust/zerocopy/src/pointer/mod.rs
index d6eacc52febe..0ce543391530 100644
--- a/rust/zerocopy/src/pointer/mod.rs
+++ b/rust/zerocopy/src/pointer/mod.rs
@@ -25,9 +25,9 @@ pub use transmute::*;
use crate::wrappers::ReadOnly;
/// A shorthand for a maybe-valid, maybe-aligned reference. Used as the argument
-/// to [`TryFromBytes::is_bit_valid`].
+/// to [`TryFromBytes::is_safe`].
///
-/// [`TryFromBytes::is_bit_valid`]: crate::TryFromBytes::is_bit_valid
+/// [`TryFromBytes::is_safe`]: crate::TryFromBytes::is_safe
pub type Maybe<'a, T, Alignment = invariant::Unaligned> =
Ptr<'a, ReadOnly<T>, (invariant::Shared, Alignment, invariant::Initialized)>;
@@ -47,10 +47,7 @@ where
pub mod cast {
use core::{marker::PhantomData, mem};
- use crate::{
- layout::{SizeInfo, TrailingSliceLayout},
- HasField, KnownLayout, PtrInner,
- };
+ use crate::{layout::SizeInfo, HasField, KnownLayout, PtrInner};
/// A pointer cast or projection.
///
@@ -182,11 +179,9 @@ pub mod cast {
// SAFETY: By the `static_assert!`, `Src` and `Dst` are either:
// - Both sized and equal in size
- // - Both slice DSTs with the same trailing slice offset and element size
- // and with align_of::<Src>() == align_of::<Dst>(). These ensure that any
- // given pointer metadata encodes the same size for both `Src` and `Dst`
- // (note that the alignment is required as it affects the amount of
- // trailing padding). Thus, `project` preserves the set of referent bytes.
+ // - Both slice DSTs with the same trailing-slice offset, the same object
+ // size for every metadata value, and with align_of::<Src>() ==
+ // align_of::<Dst>(). Thus, `project` preserves the set of referent bytes.
unsafe impl<Src, Dst> Project<Src, Dst> for CastUnsized
where
Src: ?Sized + KnownLayout,
@@ -201,10 +196,11 @@ pub mod cast {
let dst = <Dst as KnownLayout>::LAYOUT;
match (src.size_info, dst.size_info) {
(SizeInfo::Sized { size: src_size }, SizeInfo::Sized { size: dst_size }) => src_size == dst_size,
- (
- SizeInfo::SliceDst(TrailingSliceLayout { offset: src_offset, elem_size: src_elem_size }),
- SizeInfo::SliceDst(TrailingSliceLayout { offset: dst_offset, elem_size: dst_elem_size })
- ) => src.align.get() == dst.align.get() && src_offset == dst_offset && src_elem_size == dst_elem_size,
+ (SizeInfo::SliceDst(src_trailing), SizeInfo::SliceDst(dst_trailing)) => {
+ src.align.get() == dst.align.get()
+ && src_trailing.offset == dst_trailing.offset
+ && src_trailing.has_same_size_sequence(dst_trailing)
+ },
_ => false,
}
});
@@ -225,10 +221,8 @@ pub mod cast {
// SAFETY: By the `static_assert!` in `Project::project`, `Src` and `Dst`
// are either:
// - Both sized and equal in size
- // - Both slice DSTs with the same alignment, trailing slice offset, and
- // element size. These ensure that any given pointer metadata encodes the
- // same size for both `Src` and `Dst` (note that the alignment is required
- // as it affects the amount of trailing padding).
+ // - Both slice DSTs with the same alignment and trailing-slice offset, and
+ // with equal sizes for every metadata value.
unsafe impl<Src, Dst> CastExact<Src, Dst> for CastUnsized
where
Src: ?Sized + KnownLayout,
@@ -240,18 +234,22 @@ pub mod cast {
///
/// A `Projection` is a [`Project`] which implements projection by
/// delegating to an implementation of [`HasField::project`].
+ ///
+ /// The `Client` parameter exists to select between implementations of
+ /// [`HasField`] that would otherwise conflict.
#[allow(missing_debug_implementations, missing_copy_implementations)]
- pub struct Projection<F: ?Sized, const VARIANT_ID: i128, const FIELD_ID: i128> {
+ pub struct Projection<Client, F: ?Sized, const VARIANT_ID: i128, const FIELD_ID: i128> {
_never: core::convert::Infallible,
+ _client: PhantomData<Client>,
_phantom: PhantomData<F>,
}
// SAFETY: `HasField::project` has the same safety post-conditions as
// `Project::project`.
- unsafe impl<T: ?Sized, F, const VARIANT_ID: i128, const FIELD_ID: i128> Project<T, T::Type>
- for Projection<F, VARIANT_ID, FIELD_ID>
+ unsafe impl<T: ?Sized, Client, F, const VARIANT_ID: i128, const FIELD_ID: i128>
+ Project<T, T::Type> for Projection<Client, F, VARIANT_ID, FIELD_ID>
where
- T: HasField<F, VARIANT_ID, FIELD_ID>,
+ T: HasField<Client, F, VARIANT_ID, FIELD_ID>,
{
#[inline(always)]
fn project(src: PtrInner<'_, T>) -> *mut T::Type {
@@ -292,10 +290,10 @@ pub mod cast {
//
// FIXME(https://github.com/rust-lang/unsafe-code-guidelines/issues/595):
// Cite the documentation once it's updated.
- unsafe impl<T: ?Sized, F, const FIELD_ID: i128> Cast<T, T::Type>
- for Projection<F, { crate::REPR_C_UNION_VARIANT_ID }, FIELD_ID>
+ unsafe impl<T: ?Sized, Client, F, const FIELD_ID: i128> Cast<T, T::Type>
+ for Projection<Client, F, { crate::REPR_C_UNION_VARIANT_ID }, FIELD_ID>
where
- T: HasField<F, { crate::REPR_C_UNION_VARIANT_ID }, FIELD_ID>,
+ T: HasField<Client, F, { crate::REPR_C_UNION_VARIANT_ID }, FIELD_ID>,
{
}
diff --git a/rust/zerocopy/src/pointer/ptr.rs b/rust/zerocopy/src/pointer/ptr.rs
index 7213f6f4a04e..0fcd2ed11d37 100644
--- a/rust/zerocopy/src/pointer/ptr.rs
+++ b/rust/zerocopy/src/pointer/ptr.rs
@@ -169,7 +169,7 @@ mod _conversions {
use crate::pointer::cast::{CastExact, CastSized, IdCast};
/// `&'a T` → `Ptr<'a, T>`
- impl<'a, T> Ptr<'a, T, (Shared, Aligned, Valid)>
+ impl<'a, T> Ptr<'a, T, (Shared, Aligned, Safe)>
where
T: 'a + ?Sized,
{
@@ -183,20 +183,19 @@ mod _conversions {
// 1. `ptr`, by invariant on `&'a T`, conforms to the alignment
// invariant of `Aligned`.
// 2. `ptr`'s referent, by invariant on `&'a T`, is a bit-valid `T`.
- // This satisfies the requirement that a `Ptr<T, (_, _, Valid)>`
+ // This satisfies the requirement that a `Ptr<T, (_, _, Safe)>`
// point to a bit-valid `T`. Even if `T` permits interior
- // mutation, this invariant guarantees that the returned `Ptr`
- // can only ever be used to modify the referent to store
- // bit-valid `T`s, which ensures that the returned `Ptr` cannot
- // be used to violate the soundness of the original `ptr: &'a T`
- // or of any other references that may exist to the same
- // referent.
+ // mutation, this invariant guarantees that the returned `Ptr` can
+ // only ever be used to modify the referent to store bit-valid
+ // `T`s, which ensures that the returned `Ptr` cannot be used to
+ // violate the soundness of the original `ptr: &'a T` or of any
+ // other references that may exist to the same referent.
unsafe { Self::from_inner(inner) }
}
}
/// `&'a mut T` → `Ptr<'a, T>`
- impl<'a, T> Ptr<'a, T, (Exclusive, Aligned, Valid)>
+ impl<'a, T> Ptr<'a, T, (Exclusive, Aligned, Safe)>
where
T: 'a + ?Sized,
{
@@ -211,7 +210,7 @@ mod _conversions {
// invariant of `Aligned`.
// 2. `ptr`'s referent, by invariant on `&'a mut T`, is a bit-valid
// `T`. This satisfies the requirement that a `Ptr<T, (_, _,
- // Valid)>` point to a bit-valid `T`. This invariant guarantees
+ // Safe)>` point to a bit-valid `T`. This invariant guarantees
// that the returned `Ptr` can only ever be used to modify the
// referent to store bit-valid `T`s, which ensures that the
// returned `Ptr` cannot be used to violate the soundness of the
@@ -224,7 +223,7 @@ mod _conversions {
impl<'a, T, I> Ptr<'a, T, I>
where
T: 'a + ?Sized,
- I: Invariants<Alignment = Aligned, Validity = Valid>,
+ I: Invariants<Alignment = Aligned, Validity = Safe>,
I::Aliasing: Reference,
{
/// Converts `self` to a shared reference.
@@ -239,7 +238,7 @@ mod _conversions {
let raw = self.as_inner().as_non_null();
// SAFETY: `self` satisfies the `Aligned` invariant, so we know that
// `raw` is validly-aligned for `T`.
- #[cfg(miri)]
+ #[cfg(all(miri, __ZEROCOPY_INTERNAL_USE_ONLY_DEV_MODE))]
unsafe {
crate::util::miri_promise_symbolic_alignment(
raw.as_ptr().cast(),
@@ -264,7 +263,7 @@ mod _conversions {
//
// 3. The pointer must point to a validly-initialized instance of
// `T`. This is ensured by-contract on `Ptr`, because the
- // `I::Validity` is `Valid`.
+ // `I::Validity` is `Safe`.
//
// 4. You must enforce Rust’s aliasing rules. This is ensured by
// contract on `Ptr`, because `I::Aliasing: Reference`. Either it
@@ -377,7 +376,7 @@ mod _conversions {
}
/// `Ptr<'a, T>` → `&'a mut T`
- impl<'a, T> Ptr<'a, T, (Exclusive, Aligned, Valid)>
+ impl<'a, T> Ptr<'a, T, (Exclusive, Aligned, Safe)>
where
T: 'a + ?Sized,
{
@@ -389,7 +388,7 @@ mod _conversions {
let mut raw = self.as_inner().as_non_null();
// SAFETY: `self` satisfies the `Aligned` invariant, so we know that
// `raw` is validly-aligned for `T`.
- #[cfg(miri)]
+ #[cfg(all(miri, __ZEROCOPY_INTERNAL_USE_ONLY_DEV_MODE))]
unsafe {
crate::util::miri_promise_symbolic_alignment(
raw.as_ptr().cast(),
@@ -413,8 +412,8 @@ mod _conversions {
// This is ensured by contract on all `PtrInner`s.
//
// 3. The pointer must point to a validly-initialized instance of
- // `T`. This is ensured by-contract on `Ptr`, because the
- // validity invariant is `Valid`.
+ // `T`. This is ensured by-contract on `Ptr`, because the validity
+ // invariant is `Safe`.
//
// 4. You must enforce Rust’s aliasing rules. This is ensured by
// contract on `Ptr`, because the `ALIASING_INVARIANT` is
@@ -431,6 +430,10 @@ mod _conversions {
where
I: Invariants,
{
+ /// Reinterprets the same byte region as `U` with validity `V`.
+ ///
+ /// This preserves the aliasing invariant, uses [`SizeEq`] to select a
+ /// [`CastExact`] implementation, and conservatively forgets alignment.
#[must_use]
#[inline(always)]
pub fn transmute<U, V, R>(self) -> Ptr<'a, U, (I::Aliasing, Unaligned, V)>
@@ -443,6 +446,12 @@ mod _conversions {
self.transmute_with::<U, V, <U as SizeEq<T>>::CastFrom, R>()
}
+ /// Reinterprets the same byte region as `U` with validity `V` using
+ /// `C`.
+ ///
+ /// `C: CastExact` preserves the byte region. The aliasing invariant is
+ /// preserved, while alignment is conservatively forgotten because the
+ /// destination type may have a different alignment requirement.
#[inline]
#[must_use]
pub fn transmute_with<U, V, C, R>(self) -> Ptr<'a, U, (I::Aliasing, Unaligned, V)>
@@ -462,11 +471,15 @@ mod _conversions {
// at the same time, as neither can perform interior mutation
// - It is directly guaranteed that it is sound for shared code to
// operate on these references simultaneously
- // - By `U: TransmuteFromPtr<T, I::Aliasing, I::Validity, C, V>`, it
+ // - By `U: TransmuteFromPtr<T, I::Aliasing, I::Validity, V, C>`, it
// is sound to perform this transmute using `C`.
unsafe { self.project_transmute_unchecked::<_, _, C>() }
}
+ /// Changes only the validity invariant to `V`.
+ ///
+ /// The referent type and byte region are unchanged, so this preserves
+ /// the existing aliasing and alignment invariants.
#[inline]
#[must_use]
pub fn recall_validity<V, R>(self) -> Ptr<'a, T, (I::Aliasing, I::Alignment, V)>
@@ -562,7 +575,7 @@ mod _conversions {
// FIXME(#1359): This should be a `transmute_with` call.
// Unfortunately, to avoid blanket impl conflicts, we only implement
// `TransmuteFrom<T>` for `Unalign<T>` (and vice versa) specifically
- // for `Valid` validity, not for all validity types.
+ // for `Safe` validity, not for all validity types.
// SAFETY:
// - By `CastSized: Cast`, `CastSized` preserves referent address,
@@ -589,7 +602,7 @@ mod _conversions {
impl<'a, T, I> Ptr<'a, T, I>
where
T: ?Sized,
- I: Invariants<Validity = Valid>,
+ I: Invariants<Validity = Safe>,
I::Aliasing: Reference,
{
/// Reads the referent.
@@ -656,6 +669,22 @@ mod _transitions {
unsafe { self.assume_invariants::<H>() }
}
+ /// Downgrades `self` to shared aliasing.
+ #[inline]
+ #[must_use]
+ pub(super) fn into_shared(self) -> Ptr<'a, T, (Shared, I::Alignment, I::Validity)>
+ where
+ I::Aliasing: Reference,
+ {
+ // SAFETY: `I::Aliasing: Reference` guarantees that the source
+ // aliasing is either `Shared` or `Exclusive`. `Shared` requires no
+ // transition. If it is `Exclusive`, consuming `self` ends the only
+ // permitted access to the referent, so the returned pointer can
+ // soundly carry `Shared` aliasing. The referent type, alignment,
+ // and validity invariants are unchanged.
+ unsafe { self.assume_invariants() }
+ }
+
/// Assumes that `self`'s referent is validly-aligned for `T` if
/// required by `A`.
///
@@ -738,40 +767,40 @@ mod _transitions {
unsafe { self.assume_validity::<Initialized>() }
}
- /// A shorthand for `self.assume_validity<Valid>()`.
+ /// A shorthand for `self.assume_validity<Safe>()`.
///
/// # Safety
///
/// The caller promises to uphold the safety preconditions of
- /// `self.assume_validity<Valid>()`.
+ /// `self.assume_validity<Safe>()`.
#[must_use]
#[inline]
- pub unsafe fn assume_valid(self) -> Ptr<'a, T, (I::Aliasing, I::Alignment, Valid)> {
+ pub unsafe fn assume_safe(self) -> Ptr<'a, T, (I::Aliasing, I::Alignment, Safe)> {
// SAFETY: The caller has promised to uphold the safety
// preconditions.
- unsafe { self.assume_validity::<Valid>() }
+ unsafe { self.assume_validity::<Safe>() }
}
/// Checks that `self`'s referent is validly initialized for `T`,
- /// returning a `Ptr` with `Valid` on success.
+ /// returning a `Ptr` with `Safe` on success.
///
/// # Panics
///
/// This method will panic if
- /// [`T::is_bit_valid`][TryFromBytes::is_bit_valid] panics.
+ /// [`T::is_safe`][TryFromBytes::is_safe] panics.
///
/// # Safety
///
/// On error, unsafe code may rely on this method's returned
/// `ValidityError` containing `self`.
#[inline]
- pub fn try_into_valid<R, S>(
+ pub fn try_into_safe<R, S>(
mut self,
- ) -> Result<Ptr<'a, T, (I::Aliasing, I::Alignment, Valid)>, ValidityError<Self, T>>
+ ) -> Result<Ptr<'a, T, (I::Aliasing, I::Alignment, Safe)>, ValidityError<Self, T>>
where
T: TryFromBytes
+ Read<I::Aliasing, R>
- + TryTransmuteFromPtr<T, I::Aliasing, I::Validity, Valid, IdCast, S>,
+ + TryTransmuteFromPtr<T, I::Aliasing, I::Validity, Safe, IdCast, S>,
ReadOnly<T>: Read<I::Aliasing, R>,
I::Aliasing: Reference,
I: Invariants<Validity = Initialized>,
@@ -779,14 +808,13 @@ mod _transitions {
// This call may panic. If that happens, it doesn't cause any
// soundness issues, as we have not generated any invalid state
// which we need to fix before returning.
- if T::is_bit_valid(self.reborrow().transmute::<_, _, _>().reborrow_shared()) {
- // SAFETY: If `T::is_bit_valid`, code may assume that `self`
- // contains a bit-valid instance of `T`. By `T:
- // TryTransmuteFromPtr<T, I::Aliasing, I::Validity, Valid>`, so
- // long as `self`'s referent conforms to the `Valid` validity
- // for `T` (which we just confirmed), then this transmute is
- // sound.
- Ok(unsafe { self.assume_valid() })
+ if T::is_safe(self.reborrow().transmute::<_, _, _>().reborrow_shared()) {
+ // SAFETY: If `T::is_safe` returns true, code may assume that
+ // `self` contains a valid `T`, so its referent conforms to
+ // `Safe` for `T`. By `T: TryTransmuteFromPtr<T, I::Aliasing,
+ // I::Validity, Safe>`, given that condition, changing `self`'s
+ // validity to `Safe` is sound.
+ Ok(unsafe { self.assume_safe() })
} else {
Err(ValidityError::new(self))
}
@@ -803,7 +831,7 @@ mod _transitions {
}
/// Casts of the referent type.
-#[cfg_attr(not(zerocopy_unstable_ptr), allow(unreachable_pub))]
+#[allow(unreachable_pub)] // False positive on MSRV
pub use _casts::TryWithError;
mod _casts {
use core::cell::UnsafeCell;
@@ -875,19 +903,22 @@ mod _casts {
}
#[inline(always)]
- pub fn project<F, const VARIANT_ID: i128, const FIELD_ID: i128>(
+ pub fn project<Client, F, const VARIANT_ID: i128, const FIELD_ID: i128>(
mut self,
) -> Result<Ptr<'a, T::Type, T::Invariants>, T::Error>
where
- T: ProjectField<F, I, VARIANT_ID, FIELD_ID>,
+ T: ProjectField<Client, F, I, VARIANT_ID, FIELD_ID>,
I::Aliasing: Reference,
{
use crate::pointer::cast::Projection;
- match T::is_projectable(self.reborrow().project_tag()) {
+ match <T as ProjectField<Client, F, I, VARIANT_ID, FIELD_ID>>::is_projectable(
+ self.reborrow().project_tag::<Client>(),
+ ) {
Ok(()) => {
let inner = self.as_inner();
- let projected = inner.project::<_, Projection<F, VARIANT_ID, FIELD_ID>>();
- // SAFETY: By `T: ProjectField<F, I, VARIANT_ID, FIELD_ID>`,
+ let projected =
+ inner.project::<_, Projection<Client, F, VARIANT_ID, FIELD_ID>>();
+ // SAFETY: By `T: ProjectField<Client, F, I, VARIANT_ID, FIELD_ID>`,
// for `self: Ptr<'_, T, I>` such that `T::is_projectable`
// (which we've verified in this match arm),
// `T::project(self.as_inner())` conforms to
@@ -908,17 +939,22 @@ mod _casts {
#[must_use]
#[inline(always)]
- pub(crate) fn project_tag(self) -> Ptr<'a, T::Tag, I>
+ pub fn project_tag<Client>(
+ self,
+ ) -> Ptr<'a, <T as HasTag<Client>>::Tag, (Shared, I::Alignment, I::Validity)>
where
- T: HasTag,
+ T: HasTag<Client>,
+ I::Aliasing: Reference,
{
- // SAFETY: By invariant on `Self::ProjectToTag`, this is a sound
- // projection.
- let tag = unsafe { self.project_transmute_unchecked::<_, _, T::ProjectToTag>() };
- // SAFETY: By invariant on `Self::ProjectToTag`, the projected
- // pointer has the same alignment as `ptr`.
- let tag = unsafe { tag.assume_alignment() };
- tag.unify_invariants()
+ let ptr = self.into_shared();
+ // SAFETY: By invariant on `ProjectToTag`, it is sound to project
+ // `ptr` to a shared tag pointer with the same validity invariant.
+ let ptr = unsafe {
+ ptr.project_transmute_unchecked::<_, _, <T as HasTag<Client>>::ProjectToTag>()
+ };
+ // SAFETY: By invariant on `ProjectToTag`, the projected pointer has
+ // the same alignment as `self`.
+ unsafe { ptr.assume_alignment() }
}
/// Attempts to transform the pointer, restoring the original on
@@ -1015,11 +1051,11 @@ mod _casts {
#[allow(clippy::wrong_self_convention)]
#[must_use]
#[inline]
- pub fn as_bytes<R>(self) -> Ptr<'a, [u8], (I::Aliasing, Aligned, Valid)>
+ pub fn as_bytes<R>(self) -> Ptr<'a, [u8], (I::Aliasing, Aligned, Safe)>
where
- [u8]: TransmuteFromPtr<T, I::Aliasing, I::Validity, Valid, AsBytesCast, R>,
+ [u8]: TransmuteFromPtr<T, I::Aliasing, I::Validity, Safe, AsBytesCast, R>,
{
- self.transmute_with::<[u8], Valid, AsBytesCast, _>().bikeshed_recall_aligned()
+ self.transmute_with::<[u8], Safe, AsBytesCast, _>().bikeshed_recall_aligned()
}
}
@@ -1071,7 +1107,7 @@ mod _casts {
/// alignment of `[u8]` is 1.
impl<'a, I> Ptr<'a, [u8], I>
where
- I: Invariants<Validity = Valid>,
+ I: Invariants<Validity = Safe>,
{
/// Attempts to cast `self` to a `U` using the given cast type.
///
@@ -1135,7 +1171,7 @@ mod _casts {
// it is derived from `try_cast_into`, which promises that the
// object described by `target` is validly aligned for `U`.
// 2. By trait bound, `self` - and thus `target` - is a bit-valid
- // `[u8]`. `Ptr<[u8], (_, _, Valid)>` and `Ptr<_, (_, _,
+ // `[u8]`. `Ptr<[u8], (_, _, Safe)>` and `Ptr<_, (_, _,
// Initialized)>` have the same bit validity, and so neither
// `self` nor `res` can be used to write a value to the referent
// which violates the other's validity invariant.
@@ -1143,14 +1179,14 @@ mod _casts {
// SAFETY:
// 0. `self` and `remainder` both have the type `[u8]`. Thus, they
- // have `UnsafeCell`s at the same locations. Type casting does
- // not affect aliasing.
+ // have `UnsafeCell`s at the same locations. Type casting does not
+ // affect aliasing.
// 1. `[u8]` has no alignment requirement.
- // 2. `self` has validity `Valid` and has type `[u8]`. Since
+ // 2. `self` has validity `Safe` and has type `[u8]`. Since
// `remainder` references a subset of `self`'s referent, it is
// also a bit-valid `[u8]`. Thus, neither `self` nor `remainder`
- // can be used to write a value to the referent which violates
- // the other's validity invariant.
+ // can be used to write a value to the referent which violates the
+ // other's validity invariant.
let remainder = unsafe { Ptr::from_inner(remainder) };
Ok((res, remainder))
@@ -1333,6 +1369,23 @@ mod tests {
use crate::util::AsAddress;
use crate::{pointer::BecauseImmutable, util::testutil::AU64, FromBytes, Immutable};
+ #[test]
+ fn test_project_tag_downgrades_aliasing() {
+ #[allow(dead_code)]
+ #[derive(zerocopy_derive::Project)]
+ #[repr(u8)]
+ enum Enum {
+ Variant(u8),
+ }
+
+ let mut value = Enum::Variant(0);
+ let _: Ptr<
+ '_,
+ <Enum as crate::HasTag<crate::project_clients::ProjectDerive>>::Tag,
+ (Shared, Aligned, Safe),
+ > = Ptr::from_mut(&mut value).project_tag::<crate::project_clients::ProjectDerive>();
+ }
+
mod test_ptr_try_cast_into_soundness {
use super::*;
diff --git a/rust/zerocopy/src/pointer/transmute.rs b/rust/zerocopy/src/pointer/transmute.rs
index ef9836698203..75f9312f622e 100644
--- a/rust/zerocopy/src/pointer/transmute.rs
+++ b/rust/zerocopy/src/pointer/transmute.rs
@@ -24,14 +24,14 @@ use crate::{
FromBytes, Immutable, IntoBytes, Unalign,
};
-/// Transmutations which are sound to attempt, conditional on validating the bit
-/// validity of the destination type.
+/// Exact pointer reinterpretations which are sound to attempt, conditional on
+/// establishing the destination validity invariant.
///
/// If a `Ptr` transmutation is `TryTransmuteFromPtr`, then it is sound to
/// perform that transmutation so long as some additional mechanism is used to
-/// validate that the referent is bit-valid for the destination type. That
-/// validation mechanism could be a type bound (such as `TransmuteFrom`) or a
-/// runtime validity check.
+/// establish that the referent is `DV`-valid for the destination type. That
+/// mechanism could be a type bound (such as `TransmuteFrom`) or a runtime
+/// validity check.
///
/// # Safety
///
@@ -49,14 +49,14 @@ use crate::{
/// Given `src: Ptr<Src, (A, _, SV)>` and `dst: Ptr<Dst, (A, Unaligned, DV)>`,
/// `Dst: TryTransmuteFromPtr<Src, A, SV, DV, C, _>` is sound if all of the
/// following hold:
-/// - Forwards transmutation: Either of the following hold:
+/// - Preserve destination validity: Either of the following hold:
/// - So long as `dst` is active, no mutation of `dst`'s referent is allowed
/// except via `dst` itself
/// - The set of `DV`-valid referents of `dst` is a superset of the set of
/// `SV`-valid referents of `src` (NOTE: this condition effectively bans
/// shrinking or overwriting transmutes, which cannot satisfy this
/// condition)
-/// - Reverse transmutation: Either of the following hold:
+/// - Preserve source validity: Either of the following hold:
/// - `dst` does not permit mutation of its referent
/// - The set of `DV`-valid referents of `dst` is a subset of the set of
/// `SV`-valid referents of `src` (NOTE: this condition effectively bans
@@ -126,7 +126,7 @@ pub unsafe trait TryTransmuteFromPtr<
pub enum BecauseMutationCompatible {}
// SAFETY:
-// - Forwards transmutation: By `Dst: MutationCompatible<Src, A, SV, DV, _>`, we
+// - Preserve destination validity: By `Dst: MutationCompatible<Src, A, SV, DV, _>`, we
// know that at least one of the following holds:
// - So long as `dst: Ptr<Dst>` is active, no mutation of its referent is
// allowed except via `dst` itself if either of the following hold:
@@ -138,17 +138,18 @@ pub enum BecauseMutationCompatible {}
// referent as `src`. By `Dst: TransmuteFrom<Src, SV, DV>`, the set of
// `DV`-valid referents of `dst` is a superset of the set of `SV`-valid
// referents of `src`.
-// - Reverse transmutation: Since the underlying cast is size-preserving, `dst`
-// addresses the same referent as `src`. By `Src: TransmuteFrom<Dst, DV, SV>`,
-// the set of `DV`-valid referents of `src` is a subset of the set of
-// `SV`-valid referents of `dst`.
+// - Preserve source validity: Since the underlying cast is size-preserving,
+// `dst` addresses the same referent as `src`. By
+// `Src: TransmuteFrom<Dst, DV, SV>`, the set of `DV`-valid referents of `dst`
+// is a subset of the set of `SV`-valid referents of `src`.
// - No safe code, given access to `src` and `dst`, can cause undefined
// behavior: By `Dst: MutationCompatible<Src, A, SV, DV, _>`, at least one of
// the following holds:
// - `A` is `Exclusive`
// - `Src: Immutable` and `Dst: Immutable`
-// - `Dst: InvariantsEq<Src>`, which guarantees that `Src` and `Dst` have the
-// same invariants, and permit interior mutation on the same byte ranges
+// - `Dst: SharedCompatible<Src>`, which guarantees that it is sound for safe
+// code to operate on `&Src` and `&Dst` pointing to the same byte range at
+// the same time
unsafe impl<Src, Dst, SV, DV, A, C, R>
TryTransmuteFromPtr<Src, A, SV, DV, C, (BecauseMutationCompatible, R)> for Dst
where
@@ -162,9 +163,9 @@ where
}
// SAFETY:
-// - Forwards transmutation: Since aliasing is `Shared` and `Src: Immutable`,
+// - Preserve destination validity: Since aliasing is `Shared` and `Src: Immutable`,
// `src` does not permit mutation of its referent.
-// - Reverse transmutation: Since aliasing is `Shared` and `Dst: Immutable`,
+// - Preserve source validity: Since aliasing is `Shared` and `Dst: Immutable`,
// `dst` does not permit mutation of its referent.
// - No safe code, given access to `src` and `dst`, can cause undefined
// behavior: `Src: Immutable` and `Dst: Immutable`
@@ -187,9 +188,9 @@ where
///
/// At least one of the following must hold:
/// - `Src: Read<A, _>` and `Self: Read<A, _>`
-/// - `Self: InvariantsEq<Src>`, and, for some `V`:
-/// - `Dst: TransmuteFrom<Src, V, V>`
-/// - `Src: TransmuteFrom<Dst, V, V>`
+/// - `Self: SharedCompatible<Src>`, and, for some `V`:
+/// - `Self: TransmuteFrom<Src, V, V>`
+/// - `Src: TransmuteFrom<Self, V, V>`
pub unsafe trait MutationCompatible<Src: ?Sized, A: Aliasing, SV, DV, R> {}
#[allow(missing_copy_implementations, missing_debug_implementations)]
@@ -204,38 +205,39 @@ where
{
}
-/// Denotes that two types have the same invariants.
+/// Denotes that shared references to two types may safely coexist on the same
+/// referent.
///
/// # Safety
///
/// It is sound for safe code to operate on a `&T` and a `&Self` pointing to the
/// same referent at the same time - no such safe code can cause undefined
/// behavior.
-pub unsafe trait InvariantsEq<T: ?Sized> {}
+pub unsafe trait SharedCompatible<T: ?Sized> {}
// SAFETY: Trivially sound to have multiple `&T` pointing to the same referent.
-unsafe impl<T: ?Sized> InvariantsEq<T> for T {}
+unsafe impl<T: ?Sized> SharedCompatible<T> for T {}
-// SAFETY: `Dst: InvariantsEq<Src> + TransmuteFrom<Src, SV, DV>`, and `Src:
+// SAFETY: `Dst: SharedCompatible<Src> + TransmuteFrom<Src, SV, DV>`, and `Src:
// TransmuteFrom<Dst, DV, SV>`.
unsafe impl<Src: ?Sized, Dst: ?Sized, A: Aliasing, SV: Validity, DV: Validity>
- MutationCompatible<Src, A, SV, DV, BecauseInvariantsEq> for Dst
+ MutationCompatible<Src, A, SV, DV, BecauseSharedCompatible> for Dst
where
Src: TransmuteFrom<Dst, DV, SV>,
- Dst: TransmuteFrom<Src, SV, DV> + InvariantsEq<Src>,
+ Dst: TransmuteFrom<Src, SV, DV> + SharedCompatible<Src>,
{
}
#[allow(missing_debug_implementations, missing_copy_implementations)]
-pub enum BecauseInvariantsEq {}
+pub enum BecauseSharedCompatible {}
-macro_rules! unsafe_impl_invariants_eq {
+macro_rules! unsafe_impl_shared_compatible {
($tyvar:ident => $t:ty, $u:ty) => {{
crate::util::macros::__unsafe();
// SAFETY: The caller promises that this is sound.
- unsafe impl<$tyvar> InvariantsEq<$t> for $u {}
+ unsafe impl<$tyvar> SharedCompatible<$t> for $u {}
// SAFETY: The caller promises that this is sound.
- unsafe impl<$tyvar> InvariantsEq<$u> for $t {}
+ unsafe impl<$tyvar> SharedCompatible<$u> for $t {}
}};
}
@@ -253,11 +255,11 @@ impl_transitive_transmute_from!(T => Wrapping<T> => T => MaybeUninit<T>);
// validity as `T`
//
// [2] https://doc.rust-lang.org/1.81.0/std/mem/struct.ManuallyDrop.html#impl-Deref-for-ManuallyDrop%3CT%3E
-unsafe impl<T: ?Sized> InvariantsEq<T> for ManuallyDrop<T> {}
+unsafe impl<T: ?Sized> SharedCompatible<T> for ManuallyDrop<T> {}
// SAFETY: See previous safety comment.
-unsafe impl<T: ?Sized> InvariantsEq<ManuallyDrop<T>> for T {}
+unsafe impl<T: ?Sized> SharedCompatible<ManuallyDrop<T>> for T {}
-/// Transmutations which are always sound.
+/// Exact pointer reinterpretations which are always sound.
///
/// `TransmuteFromPtr` is a shorthand for [`TryTransmuteFromPtr`] and
/// [`TransmuteFrom`].
@@ -293,8 +295,12 @@ where
{
}
-/// Denotes that any `SV`-valid `Src` may soundly be transmuted into a
-/// `DV`-valid `Self`.
+/// Denotes that, for equally-sized referents, every bit pattern allowed for an
+/// `SV`-valid `Src` is also allowed for a `DV`-valid `Self`.
+///
+/// `TransmuteFrom` does not by itself authorize a pointer transmutation. It
+/// provides a directional validity implication used by the pointer-transmutation
+/// machinery.
///
/// # Safety
///
@@ -333,7 +339,7 @@ impl<T: ?Sized> SizeEq<T> for T {
// SAFETY: Since `Src: IntoBytes`, the set of valid `Src`'s is the set of
// initialized bit patterns, which is exactly the set allowed in the referent of
// any `Initialized` `Ptr`.
-unsafe impl<Src, Dst> TransmuteFrom<Src, Valid, Initialized> for Dst
+unsafe impl<Src, Dst> TransmuteFrom<Src, Safe, Initialized> for Dst
where
Src: IntoBytes + ?Sized,
Dst: ?Sized,
@@ -341,18 +347,19 @@ where
}
// SAFETY: Since `Dst: FromBytes`, any initialized bit pattern may appear in the
-// referent of a `Ptr<Dst, (_, _, Valid)>`. This is exactly equal to the set of
+// referent of a `Ptr<Dst, (_, _, Safe)>`. This is exactly equal to the set of
// bit patterns which may appear in the referent of any `Initialized` `Ptr`.
-unsafe impl<Src, Dst> TransmuteFrom<Src, Initialized, Valid> for Dst
+unsafe impl<Src, Dst> TransmuteFrom<Src, Initialized, Safe> for Dst
where
Src: ?Sized,
Dst: FromBytes + ?Sized,
{
}
-// FIXME(#2354): This seems like a smell - the soundness of this bound has
-// nothing to do with `Src` or `Dst` - we're basically just saying `[u8; N]` is
-// transmutable into `[u8; N]`.
+// FIXME(#2354): This relation does not depend on `Src` or `Dst`. That is
+// expected semantically: `Initialized` permits the same states regardless of
+// referent type. The awkward part is encoding that validity-state relation as a
+// trait relation between referent types.
// SAFETY: The set of allowed bit patterns in the referent of any `Initialized`
// `Ptr` is the same regardless of referent type.
@@ -363,9 +370,10 @@ where
{
}
-// FIXME(#2354): This seems like a smell - the soundness of this bound has
-// nothing to do with `Dst` - we're basically just saying that any type is
-// transmutable into `MaybeUninit<[u8; N]>`.
+// FIXME(#2354): This relation does not depend on `Src` or `Dst`. That is
+// expected semantically: every validity state implies `Uninit`, which permits
+// any byte sequence. The awkward part is encoding that validity-state relation
+// as a trait relation between referent types.
// SAFETY: A `Dst` with validity `Uninit` permits any byte sequence, and
// therefore can be transmuted from any value.
@@ -400,7 +408,7 @@ const _: () = unsafe { unsafe_impl_for_transparent_wrapper!(pub T => Unalign<T>)
// sound for these two references to exist at the same time since it's already
// possible for safe code to get into this state.
#[allow(clippy::multiple_unsafe_ops_per_block)]
-const _: () = unsafe { unsafe_impl_invariants_eq!(T => T, Unalign<T>) };
+const _: () = unsafe { unsafe_impl_shared_compatible!(T => T, Unalign<T>) };
// SAFETY:
// - `Wrapping<T>` has the same size as `T` [1].
@@ -433,7 +441,7 @@ const _: () = unsafe { unsafe_impl_for_transparent_wrapper!(pub T => Wrapping<T>
// already possible for safe code to obtain a `&Wrapping<T>` and a `&T` pointing
// to the same referent at the same time. Thus, this must be sound.
#[allow(clippy::multiple_unsafe_ops_per_block)]
-const _: () = unsafe { unsafe_impl_invariants_eq!(T => T, Wrapping<T>) };
+const _: () = unsafe { unsafe_impl_shared_compatible!(T => T, Wrapping<T>) };
// SAFETY:
// - `UnsafeCell<T>` has the same size as `T` [1].
@@ -478,7 +486,7 @@ impl_transitive_transmute_from!(T: ?Sized => UnsafeCell<T> => T => Cell<T>);
// explicitly guaranteed, but it's obvious from `MaybeUninit`'s documentation
// that this is the intention:
// https://doc.rust-lang.org/1.85.0/core/mem/union.MaybeUninit.html
-unsafe impl<T> TransmuteFrom<T, Uninit, Valid> for MaybeUninit<T> {}
+unsafe impl<T> TransmuteFrom<T, Uninit, Safe> for MaybeUninit<T> {}
impl<T> SizeEq<T> for MaybeUninit<T> {
type CastFrom = CastSizedExact;