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