xref: /linux/rust/zerocopy/src/pointer/transmute.rs (revision 12d5fc96ebbb3b948861805b32a4c3a96105ccd9)
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 /// Exact pointer reinterpretations which are sound to attempt, conditional on
28 /// establishing the destination validity invariant.
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 /// establish that the referent is `DV`-valid for the destination type. That
33 /// mechanism could be a type bound (such as `TransmuteFrom`) or a runtime
34 /// 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 /// - Preserve destination validity: 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 /// - Preserve source validity: 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 // - Preserve destination validity: 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 // - Preserve source validity: Since the underlying cast is size-preserving,
142 //   `dst` addresses the same referent as `src`. By
143 //   `Src: TransmuteFrom<Dst, DV, SV>`, the set of `DV`-valid referents of `dst`
144 //   is a subset of the set of `SV`-valid referents of `src`.
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: SharedCompatible<Src>`, which guarantees that it is sound for safe
151 //     code to operate on `&Src` and `&Dst` pointing to the same byte range at
152 //     the same time
153 unsafe impl<Src, Dst, SV, DV, A, C, R>
154     TryTransmuteFromPtr<Src, A, SV, DV, C, (BecauseMutationCompatible, R)> for Dst
155 where
156     A: Aliasing,
157     SV: Validity,
158     DV: Validity,
159     Src: TransmuteFrom<Dst, DV, SV> + ?Sized,
160     Dst: MutationCompatible<Src, A, SV, DV, R> + ?Sized,
161     C: CastExact<Src, Dst>,
162 {
163 }
164 
165 // SAFETY:
166 // - Preserve destination validity: Since aliasing is `Shared` and `Src: Immutable`,
167 //   `src` does not permit mutation of its referent.
168 // - Preserve source validity: Since aliasing is `Shared` and `Dst: Immutable`,
169 //   `dst` does not permit mutation of its referent.
170 // - No safe code, given access to `src` and `dst`, can cause undefined
171 //   behavior: `Src: Immutable` and `Dst: Immutable`
172 unsafe impl<Src, Dst, SV, DV, C> TryTransmuteFromPtr<Src, Shared, SV, DV, C, BecauseImmutable>
173     for Dst
174 where
175     SV: Validity,
176     DV: Validity,
177     Src: Immutable + ?Sized,
178     Dst: Immutable + ?Sized,
179     C: CastExact<Src, Dst>,
180 {
181 }
182 
183 /// Denotes that `src: Ptr<Src, (A, _, SV)>` and `dst: Ptr<Self, (A, _, DV)>`,
184 /// referencing the same referent at the same time, cannot be used by safe code
185 /// to break library safety invariants of `Src` or `Self`.
186 ///
187 /// # Safety
188 ///
189 /// At least one of the following must hold:
190 /// - `Src: Read<A, _>` and `Self: Read<A, _>`
191 /// - `Self: SharedCompatible<Src>`, and, for some `V`:
192 ///   - `Self: TransmuteFrom<Src, V, V>`
193 ///   - `Src: TransmuteFrom<Self, V, V>`
194 pub unsafe trait MutationCompatible<Src: ?Sized, A: Aliasing, SV, DV, R> {}
195 
196 #[allow(missing_copy_implementations, missing_debug_implementations)]
197 pub enum BecauseRead {}
198 
199 // SAFETY: `Src: Read<A, _>` and `Dst: Read<A, _>`.
200 unsafe impl<Src: ?Sized, Dst: ?Sized, A: Aliasing, SV: Validity, DV: Validity, R>
201     MutationCompatible<Src, A, SV, DV, (BecauseRead, R)> for Dst
202 where
203     Src: Read<A, R>,
204     Dst: Read<A, R>,
205 {
206 }
207 
208 /// Denotes that shared references to two types may safely coexist on the same
209 /// referent.
210 ///
211 /// # Safety
212 ///
213 /// It is sound for safe code to operate on a `&T` and a `&Self` pointing to the
214 /// same referent at the same time - no such safe code can cause undefined
215 /// behavior.
216 pub unsafe trait SharedCompatible<T: ?Sized> {}
217 
218 // SAFETY: Trivially sound to have multiple `&T` pointing to the same referent.
219 unsafe impl<T: ?Sized> SharedCompatible<T> for T {}
220 
221 // SAFETY: `Dst: SharedCompatible<Src> + TransmuteFrom<Src, SV, DV>`, and `Src:
222 // TransmuteFrom<Dst, DV, SV>`.
223 unsafe impl<Src: ?Sized, Dst: ?Sized, A: Aliasing, SV: Validity, DV: Validity>
224     MutationCompatible<Src, A, SV, DV, BecauseSharedCompatible> for Dst
225 where
226     Src: TransmuteFrom<Dst, DV, SV>,
227     Dst: TransmuteFrom<Src, SV, DV> + SharedCompatible<Src>,
228 {
229 }
230 
231 #[allow(missing_debug_implementations, missing_copy_implementations)]
232 pub enum BecauseSharedCompatible {}
233 
234 macro_rules! unsafe_impl_shared_compatible {
235     ($tyvar:ident => $t:ty, $u:ty) => {{
236         crate::util::macros::__unsafe();
237         // SAFETY: The caller promises that this is sound.
238         unsafe impl<$tyvar> SharedCompatible<$t> for $u {}
239         // SAFETY: The caller promises that this is sound.
240         unsafe impl<$tyvar> SharedCompatible<$u> for $t {}
241     }};
242 }
243 
244 impl_transitive_transmute_from!(T => MaybeUninit<T> => T => Wrapping<T>);
245 impl_transitive_transmute_from!(T => Wrapping<T> => T => MaybeUninit<T>);
246 
247 // SAFETY: `ManuallyDrop<T>` has the same size and bit validity as `T` [1], and
248 // implements `Deref<Target = T>` [2]. Thus, it is already possible for safe
249 // code to obtain a `&T` and a `&ManuallyDrop<T>` to the same referent at the
250 // same time.
251 //
252 // [1] Per https://doc.rust-lang.org/1.81.0/std/mem/struct.ManuallyDrop.html:
253 //
254 //   `ManuallyDrop<T>` is guaranteed to have the same layout and bit
255 //   validity as `T`
256 //
257 // [2] https://doc.rust-lang.org/1.81.0/std/mem/struct.ManuallyDrop.html#impl-Deref-for-ManuallyDrop%3CT%3E
258 unsafe impl<T: ?Sized> SharedCompatible<T> for ManuallyDrop<T> {}
259 // SAFETY: See previous safety comment.
260 unsafe impl<T: ?Sized> SharedCompatible<ManuallyDrop<T>> for T {}
261 
262 /// Exact pointer reinterpretations which are always sound.
263 ///
264 /// `TransmuteFromPtr` is a shorthand for [`TryTransmuteFromPtr`] and
265 /// [`TransmuteFrom`].
266 ///
267 /// # Safety
268 ///
269 /// `Dst: TransmuteFromPtr<Src, A, SV, DV, _>` is equivalent to `Dst:
270 /// TryTransmuteFromPtr<Src, A, SV, DV, _> + TransmuteFrom<Src, SV, DV>`.
271 pub unsafe trait TransmuteFromPtr<
272     Src: ?Sized,
273     A: Aliasing,
274     SV: Validity,
275     DV: Validity,
276     C: CastExact<Src, Self>,
277     R,
278 >: TryTransmuteFromPtr<Src, A, SV, DV, C, R> + TransmuteFrom<Src, SV, DV>
279 {
280 }
281 
282 // SAFETY: The `where` bounds are equivalent to the safety invariant on
283 // `TransmuteFromPtr`.
284 unsafe impl<
285         Src: ?Sized,
286         Dst: ?Sized,
287         A: Aliasing,
288         SV: Validity,
289         DV: Validity,
290         C: CastExact<Src, Dst>,
291         R,
292     > TransmuteFromPtr<Src, A, SV, DV, C, R> for Dst
293 where
294     Dst: TransmuteFrom<Src, SV, DV> + TryTransmuteFromPtr<Src, A, SV, DV, C, R>,
295 {
296 }
297 
298 /// Denotes that, for equally-sized referents, every bit pattern allowed for an
299 /// `SV`-valid `Src` is also allowed for a `DV`-valid `Self`.
300 ///
301 /// `TransmuteFrom` does not by itself authorize a pointer transmutation. It
302 /// provides a directional validity implication used by the pointer-transmutation
303 /// machinery.
304 ///
305 /// # Safety
306 ///
307 /// Given `src: Ptr<Src, (_, _, SV)>` and `dst: Ptr<Dst, (_, _, DV)>`, if the
308 /// referents of `src` and `dst` are the same size, then the set of bit patterns
309 /// allowed to appear in `src`'s referent must be a subset of the set allowed to
310 /// appear in `dst`'s referent.
311 ///
312 /// If the referents are not the same size, then `Dst: TransmuteFrom<Src, SV,
313 /// DV>` conveys no safety guarantee.
314 pub unsafe trait TransmuteFrom<Src: ?Sized, SV, DV> {}
315 
316 /// Carries the ability to perform a size-preserving cast or conversion from a
317 /// raw pointer to `Src` to a raw pointer to `Self`.
318 ///
319 /// The cast/conversion is carried by the associated [`CastFrom`] type, and
320 /// may be a no-op cast (without updating pointer metadata) or a conversion
321 /// which updates pointer metadata.
322 ///
323 /// # Safety
324 ///
325 /// `SizeEq` on its own conveys no safety guarantee. Any safety guarantees come
326 /// from the safety invariants on the associated [`CastFrom`] type, specifically
327 /// the [`CastExact`] bound.
328 ///
329 /// [`CastFrom`]: SizeEq::CastFrom
330 /// [`CastExact`]: CastExact
331 pub trait SizeEq<Src: ?Sized> {
332     type CastFrom: CastExact<Src, Self>;
333 }
334 
335 impl<T: ?Sized> SizeEq<T> for T {
336     type CastFrom = cast::IdCast;
337 }
338 
339 // SAFETY: Since `Src: IntoBytes`, the set of valid `Src`'s is the set of
340 // initialized bit patterns, which is exactly the set allowed in the referent of
341 // any `Initialized` `Ptr`.
342 unsafe impl<Src, Dst> TransmuteFrom<Src, Safe, Initialized> for Dst
343 where
344     Src: IntoBytes + ?Sized,
345     Dst: ?Sized,
346 {
347 }
348 
349 // SAFETY: Since `Dst: FromBytes`, any initialized bit pattern may appear in the
350 // referent of a `Ptr<Dst, (_, _, Safe)>`. This is exactly equal to the set of
351 // bit patterns which may appear in the referent of any `Initialized` `Ptr`.
352 unsafe impl<Src, Dst> TransmuteFrom<Src, Initialized, Safe> for Dst
353 where
354     Src: ?Sized,
355     Dst: FromBytes + ?Sized,
356 {
357 }
358 
359 // FIXME(#2354): This relation does not depend on `Src` or `Dst`. That is
360 // expected semantically: `Initialized` permits the same states regardless of
361 // referent type. The awkward part is encoding that validity-state relation as a
362 // trait relation between referent types.
363 
364 // SAFETY: The set of allowed bit patterns in the referent of any `Initialized`
365 // `Ptr` is the same regardless of referent type.
366 unsafe impl<Src, Dst> TransmuteFrom<Src, Initialized, Initialized> for Dst
367 where
368     Src: ?Sized,
369     Dst: ?Sized,
370 {
371 }
372 
373 // FIXME(#2354): This relation does not depend on `Src` or `Dst`. That is
374 // expected semantically: every validity state implies `Uninit`, which permits
375 // any byte sequence. The awkward part is encoding that validity-state relation
376 // as a trait relation between referent types.
377 
378 // SAFETY: A `Dst` with validity `Uninit` permits any byte sequence, and
379 // therefore can be transmuted from any value.
380 unsafe impl<Src, Dst, V> TransmuteFrom<Src, V, Uninit> for Dst
381 where
382     Src: ?Sized,
383     Dst: ?Sized,
384     V: Validity,
385 {
386 }
387 
388 // SAFETY:
389 // - `ManuallyDrop<T>` has the same size as `T` [1]
390 // - `ManuallyDrop<T>` has the same validity as `T` [1]
391 //
392 // [1] Per https://doc.rust-lang.org/1.81.0/std/mem/struct.ManuallyDrop.html:
393 //
394 //   `ManuallyDrop<T>` is guaranteed to have the same layout and bit validity as
395 //   `T`
396 #[allow(clippy::multiple_unsafe_ops_per_block)]
397 const _: () = unsafe { unsafe_impl_for_transparent_wrapper!(pub T: ?Sized => ManuallyDrop<T>) };
398 
399 // SAFETY:
400 // - `Unalign<T>` promises to have the same size as `T`.
401 // - `Unalign<T>` promises to have the same validity as `T`.
402 #[allow(clippy::multiple_unsafe_ops_per_block)]
403 const _: () = unsafe { unsafe_impl_for_transparent_wrapper!(pub T => Unalign<T>) };
404 // SAFETY: `Unalign<T>` promises to have the same size and validity as `T`.
405 // Given `u: &Unalign<T>`, it is already possible to obtain `let t =
406 // u.try_deref().unwrap()`. Because `Unalign<T>` has the same size as `T`, the
407 // returned `&T` must point to the same referent as `u`, and thus it must be
408 // sound for these two references to exist at the same time since it's already
409 // possible for safe code to get into this state.
410 #[allow(clippy::multiple_unsafe_ops_per_block)]
411 const _: () = unsafe { unsafe_impl_shared_compatible!(T => T, Unalign<T>) };
412 
413 // SAFETY:
414 // - `Wrapping<T>` has the same size as `T` [1].
415 // - `Wrapping<T>` has only one field, which is `pub` [2]. We are also
416 //   guaranteed per that `Wrapping<T>` has the same layout as `T` [1]. The only
417 //   way for both of these to be true simultaneously is for `Wrapping<T>` to
418 //   have the same bit validity as `T`. In particular, in order to change the
419 //   bit validity, one of the following would need to happen:
420 //   - `Wrapping` could change its `repr`, but this would violate the layout
421 //     guarantee.
422 //   - `Wrapping` could add or change its fields, but this would be a
423 //     stability-breaking change.
424 //
425 // [1] Per https://doc.rust-lang.org/1.85.0/core/num/struct.Wrapping.html#layout-1:
426 //
427 //   `Wrapping<T>` is guaranteed to have the same layout and ABI as `T`.
428 //
429 // [2] Definition from https://doc.rust-lang.org/1.85.0/core/num/struct.Wrapping.html:
430 //
431 //   ```
432 //   #[repr(transparent)]
433 //   pub struct Wrapping<T>(pub T);
434 //   ```
435 #[allow(clippy::multiple_unsafe_ops_per_block)]
436 const _: () = unsafe { unsafe_impl_for_transparent_wrapper!(pub T => Wrapping<T>) };
437 
438 // SAFETY: By the preceding safety proof, `Wrapping<T>` and `T` have the same
439 // layout and bit validity. Since a `Wrapping<T>`'s `T` field is `pub`, given
440 // `w: &Wrapping<T>`, it's possible to do `let t = &w.t`, which means that it's
441 // already possible for safe code to obtain a `&Wrapping<T>` and a `&T` pointing
442 // to the same referent at the same time. Thus, this must be sound.
443 #[allow(clippy::multiple_unsafe_ops_per_block)]
444 const _: () = unsafe { unsafe_impl_shared_compatible!(T => T, Wrapping<T>) };
445 
446 // SAFETY:
447 // - `UnsafeCell<T>` has the same size as `T` [1].
448 // - Per [1], `UnsafeCell<T>` has the same bit validity as `T`. Technically the
449 //   term "representation" doesn't guarantee this, but the subsequent sentence
450 //   in the documentation makes it clear that this is the intention.
451 //
452 // [1] Per https://doc.rust-lang.org/1.81.0/core/cell/struct.UnsafeCell.html#memory-layout:
453 //
454 //   `UnsafeCell<T>` has the same in-memory representation as its inner type
455 //   `T`. A consequence of this guarantee is that it is possible to convert
456 //   between `T` and `UnsafeCell<T>`.
457 #[allow(clippy::multiple_unsafe_ops_per_block)]
458 const _: () = unsafe { unsafe_impl_for_transparent_wrapper!(pub T: ?Sized => UnsafeCell<T>) };
459 
460 // SAFETY:
461 // - `Cell<T>` has the same size as `T` [1].
462 // - Per [1], `Cell<T>` has the same bit validity as `T`. Technically the term
463 //   "representation" doesn't guarantee this, but it does promise to have the
464 //   "same memory layout and caveats as `UnsafeCell<T>`." The `UnsafeCell` docs
465 //   [2] make it clear that bit validity is the intention even if that phrase
466 //   isn't used.
467 //
468 // [1] Per https://doc.rust-lang.org/1.85.0/std/cell/struct.Cell.html#memory-layout:
469 //
470 //   `Cell<T>` has the same memory layout and caveats as `UnsafeCell<T>`. In
471 //   particular, this means that `Cell<T>` has the same in-memory representation
472 //   as its inner type `T`.
473 //
474 // [2] Per https://doc.rust-lang.org/1.81.0/core/cell/struct.UnsafeCell.html#memory-layout:
475 //
476 //   `UnsafeCell<T>` has the same in-memory representation as its inner type
477 //   `T`. A consequence of this guarantee is that it is possible to convert
478 //   between `T` and `UnsafeCell<T>`.
479 #[allow(clippy::multiple_unsafe_ops_per_block)]
480 const _: () = unsafe { unsafe_impl_for_transparent_wrapper!(pub T: ?Sized => Cell<T>) };
481 
482 impl_transitive_transmute_from!(T: ?Sized => Cell<T> => T => UnsafeCell<T>);
483 impl_transitive_transmute_from!(T: ?Sized => UnsafeCell<T> => T => Cell<T>);
484 
485 // SAFETY: `MaybeUninit<T>` has no validity requirements. Currently this is not
486 // explicitly guaranteed, but it's obvious from `MaybeUninit`'s documentation
487 // that this is the intention:
488 // https://doc.rust-lang.org/1.85.0/core/mem/union.MaybeUninit.html
489 unsafe impl<T> TransmuteFrom<T, Uninit, Safe> for MaybeUninit<T> {}
490 
491 impl<T> SizeEq<T> for MaybeUninit<T> {
492     type CastFrom = CastSizedExact;
493 }
494 
495 impl<T> SizeEq<MaybeUninit<T>> for T {
496     type CastFrom = CastSizedExact;
497 }
498 
499 #[cfg(test)]
500 mod tests {
501     use super::*;
502     use crate::pointer::cast::Project as _;
503 
504     fn test_size_eq<Src, Dst: SizeEq<Src>>(mut src: Src) {
505         let _: *mut Dst =
506             <Dst as SizeEq<Src>>::CastFrom::project(crate::pointer::PtrInner::from_mut(&mut src));
507     }
508 
509     #[test]
510     fn test_transmute_coverage() {
511         // SizeEq<T> for MaybeUninit<T>
512         test_size_eq::<u8, MaybeUninit<u8>>(0u8);
513 
514         // SizeEq<MaybeUninit<T>> for T
515         test_size_eq::<MaybeUninit<u8>, u8>(MaybeUninit::<u8>::new(0));
516 
517         // Transitive: MaybeUninit<T> -> Wrapping<T>
518         // T => MaybeUninit<T> => T => Wrapping<T>
519         test_size_eq::<u8, Wrapping<u8>>(0u8);
520 
521         // T => Wrapping<T> => T => MaybeUninit<T>
522         test_size_eq::<Wrapping<u8>, MaybeUninit<u8>>(Wrapping(0u8));
523 
524         // T: ?Sized => Cell<T> => T => UnsafeCell<T>
525         test_size_eq::<Cell<u8>, UnsafeCell<u8>>(Cell::new(0u8));
526 
527         // T: ?Sized => UnsafeCell<T> => T => Cell<T>
528         test_size_eq::<UnsafeCell<u8>, Cell<u8>>(UnsafeCell::new(0u8));
529     }
530 }
531