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