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