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