Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 19 additions & 7 deletions src/pointer/ptr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -382,11 +382,20 @@ mod _conversions {
where
V: Validity,
U: TransmuteFromPtr<T, I::Aliasing, I::Validity, V, R> + SizeEq<T> + ?Sized,
{
self.transmute_with::<U, V, <U as SizeEq<T>>::CastFrom, R>()
}

pub(crate) fn transmute_with<U, V, C, R>(self) -> Ptr<'a, U, (I::Aliasing, Unaligned, V)>
where
V: Validity,
U: TransmuteFromPtr<T, I::Aliasing, I::Validity, V, R> + ?Sized,
C: crate::pointer::cast::CastExact<T, U>,
{
// SAFETY:
// - By `SizeEq::CastFrom: Cast`, `SizeEq::CastFrom` preserves
// referent address, and so we don't need to consider projections
// in the following safety arguments.
// - By `C: CastExact`, `C` preserves referent address, and so we
// don't need to consider projections in the following safety
// arguments.
// - If aliasing is `Shared`, then by `U: TransmuteFromPtr<T>`, at
// least one of the following holds:
// - `T: Immutable` and `U: Immutable`, in which case it is
Expand All @@ -395,8 +404,10 @@ mod _conversions {
// - 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, V>`, it is
// sound to perform this transmute.
unsafe { self.project_transmute_unchecked::<_, _, <U as SizeEq<T>>::CastFrom>() }
// sound to perform this transmute using an address- and
// size-preserving cast. By `C: CastExact`, `C` is address- and
// size-preserving.
unsafe { self.project_transmute_unchecked::<_, _, C>() }
}

#[doc(hidden)]
Expand All @@ -414,9 +425,10 @@ mod _conversions {
// - It is trivially sound to have multiple `&T` referencing the
// same referent simultaneously
// - By `T: TransmuteFromPtr<T, I::Aliasing, I::Validity, V>`, it is
// sound to perform this transmute.
// sound to perform this transmute using an address- and
// size-preserving cast (which `IdCast` is).
let ptr =
unsafe { self.project_transmute_unchecked::<_, _, <T as SizeEq<T>>::CastFrom>() };
unsafe { self.project_transmute_unchecked::<_, _, crate::pointer::cast::IdCast>() };
// SAFETY: `self` and `ptr` have the same address and referent type.
// Therefore, if `self` satisfies `I::Alignment`, then so does
// `ptr`.
Expand Down
42 changes: 18 additions & 24 deletions src/pointer/transmute.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ use crate::{
///
/// Given `src: Ptr<'a, Src, (A, _, SV)>`, if the referent of `src` is
/// `DV`-valid for `Dst`, then it is sound to transmute `src` into `dst: Ptr<'a,
/// Dst, (A, Unaligned, DV)>` using `<Dst as SizeEq<Src>>::CastFrom::project`.
/// Dst, (A, Unaligned, DV)>` using a address- and size-preserving cast.
///
/// ## Pre-conditions
///
Expand Down Expand Up @@ -67,17 +67,14 @@ use crate::{
/// Given:
/// - `src: Ptr<'a, Src, (A, _, SV)>`
/// - `src`'s referent is `DV`-valid for `Dst`
/// - `Dst: SizeEq<Src>`
///
/// We are trying to prove that it is sound to cast using `<Dst as
/// SizeEq<Src>>::CastFrom::project` from `src` to a `dst: Ptr<'a, Dst, (A,
/// Unaligned, DV)>`. We need to prove that such a transmute does not violate
/// any of `src`'s invariants, and that it satisfies all invariants of the
/// destination `Ptr` type.
/// We are trying to prove that it is sound to perform a size-preserving cast
/// from `src` to a `dst: Ptr<'a, Dst, (A, Unaligned, DV)>`. We need to prove
/// that such a cast does not violate any of `src`'s invariants, and that it
/// satisfies all invariants of the destination `Ptr` type.
///
/// First, by `SizeEq::CastFrom: CastExact`, `src`'s address is unchanged, so it
/// still satisfies its alignment. Since `dst`'s alignment is `Unaligned`, it
/// trivially satisfies its alignment.
/// First, `src`'s address is unchanged, so it still satisfies its alignment.
/// Since `dst`'s alignment is `Unaligned`, it trivially satisfies its alignment.
///
/// Second, aliasing is either `Exclusive` or `Shared`:
/// - If it is `Exclusive`, then both `src` and `dst` satisfy `Exclusive`
Expand Down Expand Up @@ -106,10 +103,7 @@ use crate::{
/// - The set of `DV`-valid referents of `dst` is a superset of the set of
/// `SV`-valid referents of `src`. Thus, any value written via `src` is
/// guaranteed to be a `DV`-valid referent of `dst`.
pub unsafe trait TryTransmuteFromPtr<Src: ?Sized, A: Aliasing, SV: Validity, DV: Validity, R>:
SizeEq<Src>
{
}
pub unsafe trait TryTransmuteFromPtr<Src: ?Sized, A: Aliasing, SV: Validity, DV: Validity, R> {}

#[allow(missing_copy_implementations, missing_debug_implementations)]
pub enum BecauseMutationCompatible {}
Expand All @@ -123,14 +117,14 @@ pub enum BecauseMutationCompatible {}
// exists, no mutation is permitted except via that `Ptr`
// - Aliasing is `Shared`, `Src: Immutable`, and `Dst: Immutable`, in which
// case no mutation is possible via either `Ptr`
// - Since the underlying cast is performed using `<Dst as SizeEq<Src>>
// ::CastFrom::project`, `dst` addresses the same bytes as `src`. By `Dst:
// TransmuteFrom<Src, SV, DV>`, the set of `DV`-valid referents of `dst` is a
// supserset of the set of `SV`-valid referents of `src`.
// - Reverse transmutation: Since the underlying cast is performed using `<Dst
// as SizeEq<Src>>::CastFrom::project`, `dst` addresses the same bytes 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`.
// - Since the underlying cast is size-preserving, `dst` addresses the same
// bytes 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 bytes 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`.
// - 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:
Expand All @@ -145,7 +139,7 @@ where
SV: Validity,
DV: Validity,
Src: TransmuteFrom<Dst, DV, SV> + ?Sized,
Dst: MutationCompatible<Src, A, SV, DV, R> + SizeEq<Src> + ?Sized,
Dst: MutationCompatible<Src, A, SV, DV, R> + ?Sized,
{
}

Expand All @@ -161,7 +155,7 @@ where
SV: Validity,
DV: Validity,
Src: Immutable + ?Sized,
Dst: Immutable + SizeEq<Src> + ?Sized,
Dst: Immutable + ?Sized,
{
}

Expand Down
Loading