Coverage Report

Created: 2026-03-31 07:09

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