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