xref: /linux/rust/zerocopy/src/pointer/transmute.rs (revision c37398010a05055e78cf0c75defb90df06c4e999)
1*c3739801SMiguel Ojeda // Copyright 2025 The Fuchsia Authors
2*c3739801SMiguel Ojeda //
3*c3739801SMiguel Ojeda // Licensed under a BSD-style license <LICENSE-BSD>, Apache License, Version 2.0
4*c3739801SMiguel Ojeda // <LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0>, or the MIT
5*c3739801SMiguel Ojeda // license <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your option.
6*c3739801SMiguel Ojeda // This file may not be copied, modified, or distributed except according to
7*c3739801SMiguel Ojeda // those terms.
8*c3739801SMiguel Ojeda 
9*c3739801SMiguel Ojeda #![allow(missing_docs)]
10*c3739801SMiguel Ojeda 
11*c3739801SMiguel Ojeda use core::{
12*c3739801SMiguel Ojeda     cell::{Cell, UnsafeCell},
13*c3739801SMiguel Ojeda     mem::{ManuallyDrop, MaybeUninit},
14*c3739801SMiguel Ojeda     num::Wrapping,
15*c3739801SMiguel Ojeda };
16*c3739801SMiguel Ojeda 
17*c3739801SMiguel Ojeda use crate::{
18*c3739801SMiguel Ojeda     pointer::{
19*c3739801SMiguel Ojeda         cast::{self, CastExact, CastSizedExact},
20*c3739801SMiguel Ojeda         invariant::*,
21*c3739801SMiguel Ojeda     },
22*c3739801SMiguel Ojeda     FromBytes, Immutable, IntoBytes, Unalign,
23*c3739801SMiguel Ojeda };
24*c3739801SMiguel Ojeda 
25*c3739801SMiguel Ojeda /// Transmutations which are sound to attempt, conditional on validating the bit
26*c3739801SMiguel Ojeda /// validity of the destination type.
27*c3739801SMiguel Ojeda ///
28*c3739801SMiguel Ojeda /// If a `Ptr` transmutation is `TryTransmuteFromPtr`, then it is sound to
29*c3739801SMiguel Ojeda /// perform that transmutation so long as some additional mechanism is used to
30*c3739801SMiguel Ojeda /// validate that the referent is bit-valid for the destination type. That
31*c3739801SMiguel Ojeda /// validation mechanism could be a type bound (such as `TransmuteFrom`) or a
32*c3739801SMiguel Ojeda /// runtime validity check.
33*c3739801SMiguel Ojeda ///
34*c3739801SMiguel Ojeda /// # Safety
35*c3739801SMiguel Ojeda ///
36*c3739801SMiguel Ojeda /// ## Post-conditions
37*c3739801SMiguel Ojeda ///
38*c3739801SMiguel Ojeda /// Given `Dst: TryTransmuteFromPtr<Src, A, SV, DV, C, _>`, callers may assume
39*c3739801SMiguel Ojeda /// the following:
40*c3739801SMiguel Ojeda ///
41*c3739801SMiguel Ojeda /// Given `src: Ptr<'a, Src, (A, _, SV)>`, if the referent of `src` is
42*c3739801SMiguel Ojeda /// `DV`-valid for `Dst`, then it is sound to transmute `src` into `dst: Ptr<'a,
43*c3739801SMiguel Ojeda /// Dst, (A, Unaligned, DV)>` using `C`.
44*c3739801SMiguel Ojeda ///
45*c3739801SMiguel Ojeda /// ## Pre-conditions
46*c3739801SMiguel Ojeda ///
47*c3739801SMiguel Ojeda /// Given `src: Ptr<Src, (A, _, SV)>` and `dst: Ptr<Dst, (A, Unaligned, DV)>`,
48*c3739801SMiguel Ojeda /// `Dst: TryTransmuteFromPtr<Src, A, SV, DV, C, _>` is sound if all of the
49*c3739801SMiguel Ojeda /// following hold:
50*c3739801SMiguel Ojeda /// - Forwards transmutation: Either of the following hold:
51*c3739801SMiguel Ojeda ///   - So long as `dst` is active, no mutation of `dst`'s referent is allowed
52*c3739801SMiguel Ojeda ///     except via `dst` itself
53*c3739801SMiguel Ojeda ///   - The set of `DV`-valid referents of `dst` is a superset of the set of
54*c3739801SMiguel Ojeda ///     `SV`-valid referents of `src` (NOTE: this condition effectively bans
55*c3739801SMiguel Ojeda ///     shrinking or overwriting transmutes, which cannot satisfy this
56*c3739801SMiguel Ojeda ///     condition)
57*c3739801SMiguel Ojeda /// - Reverse transmutation: Either of the following hold:
58*c3739801SMiguel Ojeda ///   - `dst` does not permit mutation of its referent
59*c3739801SMiguel Ojeda ///   - The set of `DV`-valid referents of `dst` is a subset of the set of
60*c3739801SMiguel Ojeda ///     `SV`-valid referents of `src` (NOTE: this condition effectively bans
61*c3739801SMiguel Ojeda ///     shrinking or overwriting transmutes, which cannot satisfy this
62*c3739801SMiguel Ojeda ///     condition)
63*c3739801SMiguel Ojeda /// - No safe code, given access to `src` and `dst`, can cause undefined
64*c3739801SMiguel Ojeda ///   behavior: Any of the following hold:
65*c3739801SMiguel Ojeda ///   - `A` is `Exclusive`
66*c3739801SMiguel Ojeda ///   - `Src: Immutable` and `Dst: Immutable`
67*c3739801SMiguel Ojeda ///   - It is sound for shared code to operate on a `&Src` and `&Dst` which
68*c3739801SMiguel Ojeda ///     reference the same byte range at the same time
69*c3739801SMiguel Ojeda ///
70*c3739801SMiguel Ojeda /// ## Proof
71*c3739801SMiguel Ojeda ///
72*c3739801SMiguel Ojeda /// Given:
73*c3739801SMiguel Ojeda /// - `src: Ptr<'a, Src, (A, _, SV)>`
74*c3739801SMiguel Ojeda /// - `src`'s referent is `DV`-valid for `Dst`
75*c3739801SMiguel Ojeda ///
76*c3739801SMiguel Ojeda /// We are trying to prove that it is sound to perform a cast from `src` to a
77*c3739801SMiguel Ojeda /// `dst: Ptr<'a, Dst, (A, Unaligned, DV)>` using `C`. We need to prove that
78*c3739801SMiguel Ojeda /// such a cast does not violate any of `src`'s invariants, and that it
79*c3739801SMiguel Ojeda /// satisfies all invariants of the destination `Ptr` type.
80*c3739801SMiguel Ojeda ///
81*c3739801SMiguel Ojeda /// First, by `C: CastExact`, `src`'s address is unchanged, so it still satisfies
82*c3739801SMiguel Ojeda /// its alignment. Since `dst`'s alignment is `Unaligned`, it trivially satisfies
83*c3739801SMiguel Ojeda /// its alignment.
84*c3739801SMiguel Ojeda ///
85*c3739801SMiguel Ojeda /// Second, aliasing is either `Exclusive` or `Shared`:
86*c3739801SMiguel Ojeda /// - If it is `Exclusive`, then both `src` and `dst` satisfy `Exclusive`
87*c3739801SMiguel Ojeda ///   aliasing trivially: since `src` and `dst` have the same lifetime, `src` is
88*c3739801SMiguel Ojeda ///   inaccessible so long as `dst` is alive, and no other live `Ptr`s or
89*c3739801SMiguel Ojeda ///   references may reference the same referent.
90*c3739801SMiguel Ojeda /// - If it is `Shared`, then either:
91*c3739801SMiguel Ojeda ///   - `Src: Immutable` and `Dst: Immutable`, and so neither `src` nor `dst`
92*c3739801SMiguel Ojeda ///     permit interior mutation.
93*c3739801SMiguel Ojeda ///   - It is explicitly sound for safe code to operate on a `&Src` and a `&Dst`
94*c3739801SMiguel Ojeda ///     pointing to the same byte range at the same time.
95*c3739801SMiguel Ojeda ///
96*c3739801SMiguel Ojeda /// Third, `src`'s validity is satisfied. By invariant, `src`'s referent began
97*c3739801SMiguel Ojeda /// as an `SV`-valid `Src`. It is guaranteed to remain so, as either of the
98*c3739801SMiguel Ojeda /// following hold:
99*c3739801SMiguel Ojeda /// - `dst` does not permit mutation of its referent.
100*c3739801SMiguel Ojeda /// - The set of `DV`-valid referents of `dst` is a subset of the set of
101*c3739801SMiguel Ojeda ///   `SV`-valid referents of `src`. Thus, any value written via `dst` is
102*c3739801SMiguel Ojeda ///   guaranteed to be an `SV`-valid referent of `src`.
103*c3739801SMiguel Ojeda ///
104*c3739801SMiguel Ojeda /// Fourth, `dst`'s validity is satisfied. It is a given of this proof that the
105*c3739801SMiguel Ojeda /// referent is `DV`-valid for `Dst`. It is guaranteed to remain so, as either
106*c3739801SMiguel Ojeda /// of the following hold:
107*c3739801SMiguel Ojeda /// - So long as `dst` is active, no mutation of the referent is allowed except
108*c3739801SMiguel Ojeda ///   via `dst` itself.
109*c3739801SMiguel Ojeda /// - The set of `DV`-valid referents of `dst` is a superset of the set of
110*c3739801SMiguel Ojeda ///   `SV`-valid referents of `src`. Thus, any value written via `src` is
111*c3739801SMiguel Ojeda ///   guaranteed to be a `DV`-valid referent of `dst`.
112*c3739801SMiguel Ojeda pub unsafe trait TryTransmuteFromPtr<
113*c3739801SMiguel Ojeda     Src: ?Sized,
114*c3739801SMiguel Ojeda     A: Aliasing,
115*c3739801SMiguel Ojeda     SV: Validity,
116*c3739801SMiguel Ojeda     DV: Validity,
117*c3739801SMiguel Ojeda     C: CastExact<Src, Self>,
118*c3739801SMiguel Ojeda     R,
119*c3739801SMiguel Ojeda >
120*c3739801SMiguel Ojeda {
121*c3739801SMiguel Ojeda }
122*c3739801SMiguel Ojeda 
123*c3739801SMiguel Ojeda #[allow(missing_copy_implementations, missing_debug_implementations)]
124*c3739801SMiguel Ojeda pub enum BecauseMutationCompatible {}
125*c3739801SMiguel Ojeda 
126*c3739801SMiguel Ojeda // SAFETY:
127*c3739801SMiguel Ojeda // - Forwards transmutation: By `Dst: MutationCompatible<Src, A, SV, DV, _>`, we
128*c3739801SMiguel Ojeda //   know that at least one of the following holds:
129*c3739801SMiguel Ojeda //   - So long as `dst: Ptr<Dst>` is active, no mutation of its referent is
130*c3739801SMiguel Ojeda //     allowed except via `dst` itself if either of the following hold:
131*c3739801SMiguel Ojeda //     - Aliasing is `Exclusive`, in which case, so long as the `Dst` `Ptr`
132*c3739801SMiguel Ojeda //       exists, no mutation is permitted except via that `Ptr`
133*c3739801SMiguel Ojeda //     - Aliasing is `Shared`, `Src: Immutable`, and `Dst: Immutable`, in which
134*c3739801SMiguel Ojeda //       case no mutation is possible via either `Ptr`
135*c3739801SMiguel Ojeda //   - Since the underlying cast is size-preserving, `dst` addresses the same
136*c3739801SMiguel Ojeda //     referent as `src`. By `Dst: TransmuteFrom<Src, SV, DV>`, the set of
137*c3739801SMiguel Ojeda //     `DV`-valid referents of `dst` is a superset of the set of `SV`-valid
138*c3739801SMiguel Ojeda //     referents of `src`.
139*c3739801SMiguel Ojeda // - Reverse transmutation: Since the underlying cast is size-preserving, `dst`
140*c3739801SMiguel Ojeda //   addresses the same referent as `src`. By `Src: TransmuteFrom<Dst, DV, SV>`,
141*c3739801SMiguel Ojeda //   the set of `DV`-valid referents of `src` is a subset of the set of
142*c3739801SMiguel Ojeda //   `SV`-valid referents of `dst`.
143*c3739801SMiguel Ojeda // - No safe code, given access to `src` and `dst`, can cause undefined
144*c3739801SMiguel Ojeda //   behavior: By `Dst: MutationCompatible<Src, A, SV, DV, _>`, at least one of
145*c3739801SMiguel Ojeda //   the following holds:
146*c3739801SMiguel Ojeda //   - `A` is `Exclusive`
147*c3739801SMiguel Ojeda //   - `Src: Immutable` and `Dst: Immutable`
148*c3739801SMiguel Ojeda //   - `Dst: InvariantsEq<Src>`, which guarantees that `Src` and `Dst` have the
149*c3739801SMiguel Ojeda //     same invariants, and permit interior mutation on the same byte ranges
150*c3739801SMiguel Ojeda unsafe impl<Src, Dst, SV, DV, A, C, R>
151*c3739801SMiguel Ojeda     TryTransmuteFromPtr<Src, A, SV, DV, C, (BecauseMutationCompatible, R)> for Dst
152*c3739801SMiguel Ojeda where
153*c3739801SMiguel Ojeda     A: Aliasing,
154*c3739801SMiguel Ojeda     SV: Validity,
155*c3739801SMiguel Ojeda     DV: Validity,
156*c3739801SMiguel Ojeda     Src: TransmuteFrom<Dst, DV, SV> + ?Sized,
157*c3739801SMiguel Ojeda     Dst: MutationCompatible<Src, A, SV, DV, R> + ?Sized,
158*c3739801SMiguel Ojeda     C: CastExact<Src, Dst>,
159*c3739801SMiguel Ojeda {
160*c3739801SMiguel Ojeda }
161*c3739801SMiguel Ojeda 
162*c3739801SMiguel Ojeda // SAFETY:
163*c3739801SMiguel Ojeda // - Forwards transmutation: Since aliasing is `Shared` and `Src: Immutable`,
164*c3739801SMiguel Ojeda //   `src` does not permit mutation of its referent.
165*c3739801SMiguel Ojeda // - Reverse transmutation: Since aliasing is `Shared` and `Dst: Immutable`,
166*c3739801SMiguel Ojeda //   `dst` does not permit mutation of its referent.
167*c3739801SMiguel Ojeda // - No safe code, given access to `src` and `dst`, can cause undefined
168*c3739801SMiguel Ojeda //   behavior: `Src: Immutable` and `Dst: Immutable`
169*c3739801SMiguel Ojeda unsafe impl<Src, Dst, SV, DV, C> TryTransmuteFromPtr<Src, Shared, SV, DV, C, BecauseImmutable>
170*c3739801SMiguel Ojeda     for Dst
171*c3739801SMiguel Ojeda where
172*c3739801SMiguel Ojeda     SV: Validity,
173*c3739801SMiguel Ojeda     DV: Validity,
174*c3739801SMiguel Ojeda     Src: Immutable + ?Sized,
175*c3739801SMiguel Ojeda     Dst: Immutable + ?Sized,
176*c3739801SMiguel Ojeda     C: CastExact<Src, Dst>,
177*c3739801SMiguel Ojeda {
178*c3739801SMiguel Ojeda }
179*c3739801SMiguel Ojeda 
180*c3739801SMiguel Ojeda /// Denotes that `src: Ptr<Src, (A, _, SV)>` and `dst: Ptr<Self, (A, _, DV)>`,
181*c3739801SMiguel Ojeda /// referencing the same referent at the same time, cannot be used by safe code
182*c3739801SMiguel Ojeda /// to break library safety invariants of `Src` or `Self`.
183*c3739801SMiguel Ojeda ///
184*c3739801SMiguel Ojeda /// # Safety
185*c3739801SMiguel Ojeda ///
186*c3739801SMiguel Ojeda /// At least one of the following must hold:
187*c3739801SMiguel Ojeda /// - `Src: Read<A, _>` and `Self: Read<A, _>`
188*c3739801SMiguel Ojeda /// - `Self: InvariantsEq<Src>`, and, for some `V`:
189*c3739801SMiguel Ojeda ///   - `Dst: TransmuteFrom<Src, V, V>`
190*c3739801SMiguel Ojeda ///   - `Src: TransmuteFrom<Dst, V, V>`
191*c3739801SMiguel Ojeda pub unsafe trait MutationCompatible<Src: ?Sized, A: Aliasing, SV, DV, R> {}
192*c3739801SMiguel Ojeda 
193*c3739801SMiguel Ojeda #[allow(missing_copy_implementations, missing_debug_implementations)]
194*c3739801SMiguel Ojeda pub enum BecauseRead {}
195*c3739801SMiguel Ojeda 
196*c3739801SMiguel Ojeda // SAFETY: `Src: Read<A, _>` and `Dst: Read<A, _>`.
197*c3739801SMiguel Ojeda unsafe impl<Src: ?Sized, Dst: ?Sized, A: Aliasing, SV: Validity, DV: Validity, R>
198*c3739801SMiguel Ojeda     MutationCompatible<Src, A, SV, DV, (BecauseRead, R)> for Dst
199*c3739801SMiguel Ojeda where
200*c3739801SMiguel Ojeda     Src: Read<A, R>,
201*c3739801SMiguel Ojeda     Dst: Read<A, R>,
202*c3739801SMiguel Ojeda {
203*c3739801SMiguel Ojeda }
204*c3739801SMiguel Ojeda 
205*c3739801SMiguel Ojeda /// Denotes that two types have the same invariants.
206*c3739801SMiguel Ojeda ///
207*c3739801SMiguel Ojeda /// # Safety
208*c3739801SMiguel Ojeda ///
209*c3739801SMiguel Ojeda /// It is sound for safe code to operate on a `&T` and a `&Self` pointing to the
210*c3739801SMiguel Ojeda /// same referent at the same time - no such safe code can cause undefined
211*c3739801SMiguel Ojeda /// behavior.
212*c3739801SMiguel Ojeda pub unsafe trait InvariantsEq<T: ?Sized> {}
213*c3739801SMiguel Ojeda 
214*c3739801SMiguel Ojeda // SAFETY: Trivially sound to have multiple `&T` pointing to the same referent.
215*c3739801SMiguel Ojeda unsafe impl<T: ?Sized> InvariantsEq<T> for T {}
216*c3739801SMiguel Ojeda 
217*c3739801SMiguel Ojeda // SAFETY: `Dst: InvariantsEq<Src> + TransmuteFrom<Src, SV, DV>`, and `Src:
218*c3739801SMiguel Ojeda // TransmuteFrom<Dst, DV, SV>`.
219*c3739801SMiguel Ojeda unsafe impl<Src: ?Sized, Dst: ?Sized, A: Aliasing, SV: Validity, DV: Validity>
220*c3739801SMiguel Ojeda     MutationCompatible<Src, A, SV, DV, BecauseInvariantsEq> for Dst
221*c3739801SMiguel Ojeda where
222*c3739801SMiguel Ojeda     Src: TransmuteFrom<Dst, DV, SV>,
223*c3739801SMiguel Ojeda     Dst: TransmuteFrom<Src, SV, DV> + InvariantsEq<Src>,
224*c3739801SMiguel Ojeda {
225*c3739801SMiguel Ojeda }
226*c3739801SMiguel Ojeda 
227*c3739801SMiguel Ojeda #[allow(missing_debug_implementations, missing_copy_implementations)]
228*c3739801SMiguel Ojeda pub enum BecauseInvariantsEq {}
229*c3739801SMiguel Ojeda 
230*c3739801SMiguel Ojeda macro_rules! unsafe_impl_invariants_eq {
231*c3739801SMiguel Ojeda     ($tyvar:ident => $t:ty, $u:ty) => {{
232*c3739801SMiguel Ojeda         crate::util::macros::__unsafe();
233*c3739801SMiguel Ojeda         // SAFETY: The caller promises that this is sound.
234*c3739801SMiguel Ojeda         unsafe impl<$tyvar> InvariantsEq<$t> for $u {}
235*c3739801SMiguel Ojeda         // SAFETY: The caller promises that this is sound.
236*c3739801SMiguel Ojeda         unsafe impl<$tyvar> InvariantsEq<$u> for $t {}
237*c3739801SMiguel Ojeda     }};
238*c3739801SMiguel Ojeda }
239*c3739801SMiguel Ojeda 
240*c3739801SMiguel Ojeda impl_transitive_transmute_from!(T => MaybeUninit<T> => T => Wrapping<T>);
241*c3739801SMiguel Ojeda impl_transitive_transmute_from!(T => Wrapping<T> => T => MaybeUninit<T>);
242*c3739801SMiguel Ojeda 
243*c3739801SMiguel Ojeda // SAFETY: `ManuallyDrop<T>` has the same size and bit validity as `T` [1], and
244*c3739801SMiguel Ojeda // implements `Deref<Target = T>` [2]. Thus, it is already possible for safe
245*c3739801SMiguel Ojeda // code to obtain a `&T` and a `&ManuallyDrop<T>` to the same referent at the
246*c3739801SMiguel Ojeda // same time.
247*c3739801SMiguel Ojeda //
248*c3739801SMiguel Ojeda // [1] Per https://doc.rust-lang.org/1.81.0/std/mem/struct.ManuallyDrop.html:
249*c3739801SMiguel Ojeda //
250*c3739801SMiguel Ojeda //   `ManuallyDrop<T>` is guaranteed to have the same layout and bit
251*c3739801SMiguel Ojeda //   validity as `T`
252*c3739801SMiguel Ojeda //
253*c3739801SMiguel Ojeda // [2] https://doc.rust-lang.org/1.81.0/std/mem/struct.ManuallyDrop.html#impl-Deref-for-ManuallyDrop%3CT%3E
254*c3739801SMiguel Ojeda unsafe impl<T: ?Sized> InvariantsEq<T> for ManuallyDrop<T> {}
255*c3739801SMiguel Ojeda // SAFETY: See previous safety comment.
256*c3739801SMiguel Ojeda unsafe impl<T: ?Sized> InvariantsEq<ManuallyDrop<T>> for T {}
257*c3739801SMiguel Ojeda 
258*c3739801SMiguel Ojeda /// Transmutations which are always sound.
259*c3739801SMiguel Ojeda ///
260*c3739801SMiguel Ojeda /// `TransmuteFromPtr` is a shorthand for [`TryTransmuteFromPtr`] and
261*c3739801SMiguel Ojeda /// [`TransmuteFrom`].
262*c3739801SMiguel Ojeda ///
263*c3739801SMiguel Ojeda /// # Safety
264*c3739801SMiguel Ojeda ///
265*c3739801SMiguel Ojeda /// `Dst: TransmuteFromPtr<Src, A, SV, DV, _>` is equivalent to `Dst:
266*c3739801SMiguel Ojeda /// TryTransmuteFromPtr<Src, A, SV, DV, _> + TransmuteFrom<Src, SV, DV>`.
267*c3739801SMiguel Ojeda pub unsafe trait TransmuteFromPtr<
268*c3739801SMiguel Ojeda     Src: ?Sized,
269*c3739801SMiguel Ojeda     A: Aliasing,
270*c3739801SMiguel Ojeda     SV: Validity,
271*c3739801SMiguel Ojeda     DV: Validity,
272*c3739801SMiguel Ojeda     C: CastExact<Src, Self>,
273*c3739801SMiguel Ojeda     R,
274*c3739801SMiguel Ojeda >: TryTransmuteFromPtr<Src, A, SV, DV, C, R> + TransmuteFrom<Src, SV, DV>
275*c3739801SMiguel Ojeda {
276*c3739801SMiguel Ojeda }
277*c3739801SMiguel Ojeda 
278*c3739801SMiguel Ojeda // SAFETY: The `where` bounds are equivalent to the safety invariant on
279*c3739801SMiguel Ojeda // `TransmuteFromPtr`.
280*c3739801SMiguel Ojeda unsafe impl<
281*c3739801SMiguel Ojeda         Src: ?Sized,
282*c3739801SMiguel Ojeda         Dst: ?Sized,
283*c3739801SMiguel Ojeda         A: Aliasing,
284*c3739801SMiguel Ojeda         SV: Validity,
285*c3739801SMiguel Ojeda         DV: Validity,
286*c3739801SMiguel Ojeda         C: CastExact<Src, Dst>,
287*c3739801SMiguel Ojeda         R,
288*c3739801SMiguel Ojeda     > TransmuteFromPtr<Src, A, SV, DV, C, R> for Dst
289*c3739801SMiguel Ojeda where
290*c3739801SMiguel Ojeda     Dst: TransmuteFrom<Src, SV, DV> + TryTransmuteFromPtr<Src, A, SV, DV, C, R>,
291*c3739801SMiguel Ojeda {
292*c3739801SMiguel Ojeda }
293*c3739801SMiguel Ojeda 
294*c3739801SMiguel Ojeda /// Denotes that any `SV`-valid `Src` may soundly be transmuted into a
295*c3739801SMiguel Ojeda /// `DV`-valid `Self`.
296*c3739801SMiguel Ojeda ///
297*c3739801SMiguel Ojeda /// # Safety
298*c3739801SMiguel Ojeda ///
299*c3739801SMiguel Ojeda /// Given `src: Ptr<Src, (_, _, SV)>` and `dst: Ptr<Dst, (_, _, DV)>`, if the
300*c3739801SMiguel Ojeda /// referents of `src` and `dst` are the same size, then the set of bit patterns
301*c3739801SMiguel Ojeda /// allowed to appear in `src`'s referent must be a subset of the set allowed to
302*c3739801SMiguel Ojeda /// appear in `dst`'s referent.
303*c3739801SMiguel Ojeda ///
304*c3739801SMiguel Ojeda /// If the referents are not the same size, then `Dst: TransmuteFrom<Src, SV,
305*c3739801SMiguel Ojeda /// DV>` conveys no safety guarantee.
306*c3739801SMiguel Ojeda pub unsafe trait TransmuteFrom<Src: ?Sized, SV, DV> {}
307*c3739801SMiguel Ojeda 
308*c3739801SMiguel Ojeda /// Carries the ability to perform a size-preserving cast or conversion from a
309*c3739801SMiguel Ojeda /// raw pointer to `Src` to a raw pointer to `Self`.
310*c3739801SMiguel Ojeda ///
311*c3739801SMiguel Ojeda /// The cast/conversion is carried by the associated [`CastFrom`] type, and
312*c3739801SMiguel Ojeda /// may be a no-op cast (without updating pointer metadata) or a conversion
313*c3739801SMiguel Ojeda /// which updates pointer metadata.
314*c3739801SMiguel Ojeda ///
315*c3739801SMiguel Ojeda /// # Safety
316*c3739801SMiguel Ojeda ///
317*c3739801SMiguel Ojeda /// `SizeEq` on its own conveys no safety guarantee. Any safety guarantees come
318*c3739801SMiguel Ojeda /// from the safety invariants on the associated [`CastFrom`] type, specifically
319*c3739801SMiguel Ojeda /// the [`CastExact`] bound.
320*c3739801SMiguel Ojeda ///
321*c3739801SMiguel Ojeda /// [`CastFrom`]: SizeEq::CastFrom
322*c3739801SMiguel Ojeda /// [`CastExact`]: CastExact
323*c3739801SMiguel Ojeda pub trait SizeEq<Src: ?Sized> {
324*c3739801SMiguel Ojeda     type CastFrom: CastExact<Src, Self>;
325*c3739801SMiguel Ojeda }
326*c3739801SMiguel Ojeda 
327*c3739801SMiguel Ojeda impl<T: ?Sized> SizeEq<T> for T {
328*c3739801SMiguel Ojeda     type CastFrom = cast::IdCast;
329*c3739801SMiguel Ojeda }
330*c3739801SMiguel Ojeda 
331*c3739801SMiguel Ojeda // SAFETY: Since `Src: IntoBytes`, the set of valid `Src`'s is the set of
332*c3739801SMiguel Ojeda // initialized bit patterns, which is exactly the set allowed in the referent of
333*c3739801SMiguel Ojeda // any `Initialized` `Ptr`.
334*c3739801SMiguel Ojeda unsafe impl<Src, Dst> TransmuteFrom<Src, Valid, Initialized> for Dst
335*c3739801SMiguel Ojeda where
336*c3739801SMiguel Ojeda     Src: IntoBytes + ?Sized,
337*c3739801SMiguel Ojeda     Dst: ?Sized,
338*c3739801SMiguel Ojeda {
339*c3739801SMiguel Ojeda }
340*c3739801SMiguel Ojeda 
341*c3739801SMiguel Ojeda // SAFETY: Since `Dst: FromBytes`, any initialized bit pattern may appear in the
342*c3739801SMiguel Ojeda // referent of a `Ptr<Dst, (_, _, Valid)>`. This is exactly equal to the set of
343*c3739801SMiguel Ojeda // bit patterns which may appear in the referent of any `Initialized` `Ptr`.
344*c3739801SMiguel Ojeda unsafe impl<Src, Dst> TransmuteFrom<Src, Initialized, Valid> for Dst
345*c3739801SMiguel Ojeda where
346*c3739801SMiguel Ojeda     Src: ?Sized,
347*c3739801SMiguel Ojeda     Dst: FromBytes + ?Sized,
348*c3739801SMiguel Ojeda {
349*c3739801SMiguel Ojeda }
350*c3739801SMiguel Ojeda 
351*c3739801SMiguel Ojeda // FIXME(#2354): This seems like a smell - the soundness of this bound has
352*c3739801SMiguel Ojeda // nothing to do with `Src` or `Dst` - we're basically just saying `[u8; N]` is
353*c3739801SMiguel Ojeda // transmutable into `[u8; N]`.
354*c3739801SMiguel Ojeda 
355*c3739801SMiguel Ojeda // SAFETY: The set of allowed bit patterns in the referent of any `Initialized`
356*c3739801SMiguel Ojeda // `Ptr` is the same regardless of referent type.
357*c3739801SMiguel Ojeda unsafe impl<Src, Dst> TransmuteFrom<Src, Initialized, Initialized> for Dst
358*c3739801SMiguel Ojeda where
359*c3739801SMiguel Ojeda     Src: ?Sized,
360*c3739801SMiguel Ojeda     Dst: ?Sized,
361*c3739801SMiguel Ojeda {
362*c3739801SMiguel Ojeda }
363*c3739801SMiguel Ojeda 
364*c3739801SMiguel Ojeda // FIXME(#2354): This seems like a smell - the soundness of this bound has
365*c3739801SMiguel Ojeda // nothing to do with `Dst` - we're basically just saying that any type is
366*c3739801SMiguel Ojeda // transmutable into `MaybeUninit<[u8; N]>`.
367*c3739801SMiguel Ojeda 
368*c3739801SMiguel Ojeda // SAFETY: A `Dst` with validity `Uninit` permits any byte sequence, and
369*c3739801SMiguel Ojeda // therefore can be transmuted from any value.
370*c3739801SMiguel Ojeda unsafe impl<Src, Dst, V> TransmuteFrom<Src, V, Uninit> for Dst
371*c3739801SMiguel Ojeda where
372*c3739801SMiguel Ojeda     Src: ?Sized,
373*c3739801SMiguel Ojeda     Dst: ?Sized,
374*c3739801SMiguel Ojeda     V: Validity,
375*c3739801SMiguel Ojeda {
376*c3739801SMiguel Ojeda }
377*c3739801SMiguel Ojeda 
378*c3739801SMiguel Ojeda // SAFETY:
379*c3739801SMiguel Ojeda // - `ManuallyDrop<T>` has the same size as `T` [1]
380*c3739801SMiguel Ojeda // - `ManuallyDrop<T>` has the same validity as `T` [1]
381*c3739801SMiguel Ojeda //
382*c3739801SMiguel Ojeda // [1] Per https://doc.rust-lang.org/1.81.0/std/mem/struct.ManuallyDrop.html:
383*c3739801SMiguel Ojeda //
384*c3739801SMiguel Ojeda //   `ManuallyDrop<T>` is guaranteed to have the same layout and bit validity as
385*c3739801SMiguel Ojeda //   `T`
386*c3739801SMiguel Ojeda #[allow(clippy::multiple_unsafe_ops_per_block)]
387*c3739801SMiguel Ojeda const _: () = unsafe { unsafe_impl_for_transparent_wrapper!(pub T: ?Sized => ManuallyDrop<T>) };
388*c3739801SMiguel Ojeda 
389*c3739801SMiguel Ojeda // SAFETY:
390*c3739801SMiguel Ojeda // - `Unalign<T>` promises to have the same size as `T`.
391*c3739801SMiguel Ojeda // - `Unalign<T>` promises to have the same validity as `T`.
392*c3739801SMiguel Ojeda #[allow(clippy::multiple_unsafe_ops_per_block)]
393*c3739801SMiguel Ojeda const _: () = unsafe { unsafe_impl_for_transparent_wrapper!(pub T => Unalign<T>) };
394*c3739801SMiguel Ojeda // SAFETY: `Unalign<T>` promises to have the same size and validity as `T`.
395*c3739801SMiguel Ojeda // Given `u: &Unalign<T>`, it is already possible to obtain `let t =
396*c3739801SMiguel Ojeda // u.try_deref().unwrap()`. Because `Unalign<T>` has the same size as `T`, the
397*c3739801SMiguel Ojeda // returned `&T` must point to the same referent as `u`, and thus it must be
398*c3739801SMiguel Ojeda // sound for these two references to exist at the same time since it's already
399*c3739801SMiguel Ojeda // possible for safe code to get into this state.
400*c3739801SMiguel Ojeda #[allow(clippy::multiple_unsafe_ops_per_block)]
401*c3739801SMiguel Ojeda const _: () = unsafe { unsafe_impl_invariants_eq!(T => T, Unalign<T>) };
402*c3739801SMiguel Ojeda 
403*c3739801SMiguel Ojeda // SAFETY:
404*c3739801SMiguel Ojeda // - `Wrapping<T>` has the same size as `T` [1].
405*c3739801SMiguel Ojeda // - `Wrapping<T>` has only one field, which is `pub` [2]. We are also
406*c3739801SMiguel Ojeda //   guaranteed per that `Wrapping<T>` has the same layout as `T` [1]. The only
407*c3739801SMiguel Ojeda //   way for both of these to be true simultaneously is for `Wrapping<T>` to
408*c3739801SMiguel Ojeda //   have the same bit validity as `T`. In particular, in order to change the
409*c3739801SMiguel Ojeda //   bit validity, one of the following would need to happen:
410*c3739801SMiguel Ojeda //   - `Wrapping` could change its `repr`, but this would violate the layout
411*c3739801SMiguel Ojeda //     guarantee.
412*c3739801SMiguel Ojeda //   - `Wrapping` could add or change its fields, but this would be a
413*c3739801SMiguel Ojeda //     stability-breaking change.
414*c3739801SMiguel Ojeda //
415*c3739801SMiguel Ojeda // [1] Per https://doc.rust-lang.org/1.85.0/core/num/struct.Wrapping.html#layout-1:
416*c3739801SMiguel Ojeda //
417*c3739801SMiguel Ojeda //   `Wrapping<T>` is guaranteed to have the same layout and ABI as `T`.
418*c3739801SMiguel Ojeda //
419*c3739801SMiguel Ojeda // [2] Definition from https://doc.rust-lang.org/1.85.0/core/num/struct.Wrapping.html:
420*c3739801SMiguel Ojeda //
421*c3739801SMiguel Ojeda //   ```
422*c3739801SMiguel Ojeda //   #[repr(transparent)]
423*c3739801SMiguel Ojeda //   pub struct Wrapping<T>(pub T);
424*c3739801SMiguel Ojeda //   ```
425*c3739801SMiguel Ojeda #[allow(clippy::multiple_unsafe_ops_per_block)]
426*c3739801SMiguel Ojeda const _: () = unsafe { unsafe_impl_for_transparent_wrapper!(pub T => Wrapping<T>) };
427*c3739801SMiguel Ojeda 
428*c3739801SMiguel Ojeda // SAFETY: By the preceding safety proof, `Wrapping<T>` and `T` have the same
429*c3739801SMiguel Ojeda // layout and bit validity. Since a `Wrapping<T>`'s `T` field is `pub`, given
430*c3739801SMiguel Ojeda // `w: &Wrapping<T>`, it's possible to do `let t = &w.t`, which means that it's
431*c3739801SMiguel Ojeda // already possible for safe code to obtain a `&Wrapping<T>` and a `&T` pointing
432*c3739801SMiguel Ojeda // to the same referent at the same time. Thus, this must be sound.
433*c3739801SMiguel Ojeda #[allow(clippy::multiple_unsafe_ops_per_block)]
434*c3739801SMiguel Ojeda const _: () = unsafe { unsafe_impl_invariants_eq!(T => T, Wrapping<T>) };
435*c3739801SMiguel Ojeda 
436*c3739801SMiguel Ojeda // SAFETY:
437*c3739801SMiguel Ojeda // - `UnsafeCell<T>` has the same size as `T` [1].
438*c3739801SMiguel Ojeda // - Per [1], `UnsafeCell<T>` has the same bit validity as `T`. Technically the
439*c3739801SMiguel Ojeda //   term "representation" doesn't guarantee this, but the subsequent sentence
440*c3739801SMiguel Ojeda //   in the documentation makes it clear that this is the intention.
441*c3739801SMiguel Ojeda //
442*c3739801SMiguel Ojeda // [1] Per https://doc.rust-lang.org/1.81.0/core/cell/struct.UnsafeCell.html#memory-layout:
443*c3739801SMiguel Ojeda //
444*c3739801SMiguel Ojeda //   `UnsafeCell<T>` has the same in-memory representation as its inner type
445*c3739801SMiguel Ojeda //   `T`. A consequence of this guarantee is that it is possible to convert
446*c3739801SMiguel Ojeda //   between `T` and `UnsafeCell<T>`.
447*c3739801SMiguel Ojeda #[allow(clippy::multiple_unsafe_ops_per_block)]
448*c3739801SMiguel Ojeda const _: () = unsafe { unsafe_impl_for_transparent_wrapper!(pub T: ?Sized => UnsafeCell<T>) };
449*c3739801SMiguel Ojeda 
450*c3739801SMiguel Ojeda // SAFETY:
451*c3739801SMiguel Ojeda // - `Cell<T>` has the same size as `T` [1].
452*c3739801SMiguel Ojeda // - Per [1], `Cell<T>` has the same bit validity as `T`. Technically the term
453*c3739801SMiguel Ojeda //   "representation" doesn't guarantee this, but it does promise to have the
454*c3739801SMiguel Ojeda //   "same memory layout and caveats as `UnsafeCell<T>`." The `UnsafeCell` docs
455*c3739801SMiguel Ojeda //   [2] make it clear that bit validity is the intention even if that phrase
456*c3739801SMiguel Ojeda //   isn't used.
457*c3739801SMiguel Ojeda //
458*c3739801SMiguel Ojeda // [1] Per https://doc.rust-lang.org/1.85.0/std/cell/struct.Cell.html#memory-layout:
459*c3739801SMiguel Ojeda //
460*c3739801SMiguel Ojeda //   `Cell<T>` has the same memory layout and caveats as `UnsafeCell<T>`. In
461*c3739801SMiguel Ojeda //   particular, this means that `Cell<T>` has the same in-memory representation
462*c3739801SMiguel Ojeda //   as its inner type `T`.
463*c3739801SMiguel Ojeda //
464*c3739801SMiguel Ojeda // [2] Per https://doc.rust-lang.org/1.81.0/core/cell/struct.UnsafeCell.html#memory-layout:
465*c3739801SMiguel Ojeda //
466*c3739801SMiguel Ojeda //   `UnsafeCell<T>` has the same in-memory representation as its inner type
467*c3739801SMiguel Ojeda //   `T`. A consequence of this guarantee is that it is possible to convert
468*c3739801SMiguel Ojeda //   between `T` and `UnsafeCell<T>`.
469*c3739801SMiguel Ojeda #[allow(clippy::multiple_unsafe_ops_per_block)]
470*c3739801SMiguel Ojeda const _: () = unsafe { unsafe_impl_for_transparent_wrapper!(pub T: ?Sized => Cell<T>) };
471*c3739801SMiguel Ojeda 
472*c3739801SMiguel Ojeda impl_transitive_transmute_from!(T: ?Sized => Cell<T> => T => UnsafeCell<T>);
473*c3739801SMiguel Ojeda impl_transitive_transmute_from!(T: ?Sized => UnsafeCell<T> => T => Cell<T>);
474*c3739801SMiguel Ojeda 
475*c3739801SMiguel Ojeda // SAFETY: `MaybeUninit<T>` has no validity requirements. Currently this is not
476*c3739801SMiguel Ojeda // explicitly guaranteed, but it's obvious from `MaybeUninit`'s documentation
477*c3739801SMiguel Ojeda // that this is the intention:
478*c3739801SMiguel Ojeda // https://doc.rust-lang.org/1.85.0/core/mem/union.MaybeUninit.html
479*c3739801SMiguel Ojeda unsafe impl<T> TransmuteFrom<T, Uninit, Valid> for MaybeUninit<T> {}
480*c3739801SMiguel Ojeda 
481*c3739801SMiguel Ojeda impl<T> SizeEq<T> for MaybeUninit<T> {
482*c3739801SMiguel Ojeda     type CastFrom = CastSizedExact;
483*c3739801SMiguel Ojeda }
484*c3739801SMiguel Ojeda 
485*c3739801SMiguel Ojeda impl<T> SizeEq<MaybeUninit<T>> for T {
486*c3739801SMiguel Ojeda     type CastFrom = CastSizedExact;
487*c3739801SMiguel Ojeda }
488*c3739801SMiguel Ojeda 
489*c3739801SMiguel Ojeda #[cfg(test)]
490*c3739801SMiguel Ojeda mod tests {
491*c3739801SMiguel Ojeda     use super::*;
492*c3739801SMiguel Ojeda     use crate::pointer::cast::Project as _;
493*c3739801SMiguel Ojeda 
494*c3739801SMiguel Ojeda     fn test_size_eq<Src, Dst: SizeEq<Src>>(mut src: Src) {
495*c3739801SMiguel Ojeda         let _: *mut Dst =
496*c3739801SMiguel Ojeda             <Dst as SizeEq<Src>>::CastFrom::project(crate::pointer::PtrInner::from_mut(&mut src));
497*c3739801SMiguel Ojeda     }
498*c3739801SMiguel Ojeda 
499*c3739801SMiguel Ojeda     #[test]
500*c3739801SMiguel Ojeda     fn test_transmute_coverage() {
501*c3739801SMiguel Ojeda         // SizeEq<T> for MaybeUninit<T>
502*c3739801SMiguel Ojeda         test_size_eq::<u8, MaybeUninit<u8>>(0u8);
503*c3739801SMiguel Ojeda 
504*c3739801SMiguel Ojeda         // SizeEq<MaybeUninit<T>> for T
505*c3739801SMiguel Ojeda         test_size_eq::<MaybeUninit<u8>, u8>(MaybeUninit::<u8>::new(0));
506*c3739801SMiguel Ojeda 
507*c3739801SMiguel Ojeda         // Transitive: MaybeUninit<T> -> Wrapping<T>
508*c3739801SMiguel Ojeda         // T => MaybeUninit<T> => T => Wrapping<T>
509*c3739801SMiguel Ojeda         test_size_eq::<u8, Wrapping<u8>>(0u8);
510*c3739801SMiguel Ojeda 
511*c3739801SMiguel Ojeda         // T => Wrapping<T> => T => MaybeUninit<T>
512*c3739801SMiguel Ojeda         test_size_eq::<Wrapping<u8>, MaybeUninit<u8>>(Wrapping(0u8));
513*c3739801SMiguel Ojeda 
514*c3739801SMiguel Ojeda         // T: ?Sized => Cell<T> => T => UnsafeCell<T>
515*c3739801SMiguel Ojeda         test_size_eq::<Cell<u8>, UnsafeCell<u8>>(Cell::new(0u8));
516*c3739801SMiguel Ojeda 
517*c3739801SMiguel Ojeda         // T: ?Sized => UnsafeCell<T> => T => Cell<T>
518*c3739801SMiguel Ojeda         test_size_eq::<UnsafeCell<u8>, Cell<u8>>(UnsafeCell::new(0u8));
519*c3739801SMiguel Ojeda     }
520*c3739801SMiguel Ojeda }
521