/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 | | } |