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