xref: /linux/rust/zerocopy/src/macros.rs (revision 056a5087d87ead77dedbe9cf5bde53b7cd4b4651)
1 // SPDX-License-Identifier: (BSD-2-Clause OR Apache-2.0) OR MIT
2 
3 // Copyright 2024 The Fuchsia Authors
4 //
5 // Licensed under the 2-Clause BSD License <LICENSE-BSD or
6 // https://opensource.org/license/bsd-2-clause>, Apache License, Version 2.0
7 // <LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0>, or the MIT
8 // license <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your option.
9 // This file may not be copied, modified, or distributed except according to
10 // those terms.
11 
12 /// Safely transmutes a value of one type to a value of another type of the same
13 /// size.
14 ///
15 /// This macro behaves like an invocation of this function:
16 ///
17 /// ```ignore
18 /// const fn transmute<Src, Dst>(src: Src) -> Dst
19 /// where
20 ///     Src: IntoBytes,
21 ///     Dst: FromBytes,
22 ///     size_of::<Src>() == size_of::<Dst>(),
23 /// {
24 /// # /*
25 ///     ...
26 /// # */
27 /// }
28 /// ```
29 ///
30 /// However, unlike a function, this macro can only be invoked when the types of
31 /// `Src` and `Dst` are completely concrete. The types `Src` and `Dst` are
32 /// inferred from the calling context; they cannot be explicitly specified in
33 /// the macro invocation.
34 ///
35 /// Note that the `Src` produced by the expression `$e` will *not* be dropped.
36 /// Semantically, its bits will be copied into a new value of type `Dst`, the
37 /// original `Src` will be forgotten, and the value of type `Dst` will be
38 /// returned.
39 ///
40 /// # `#![allow(shrink)]`
41 ///
42 /// If `#![allow(shrink)]` is provided, `transmute!` additionally supports
43 /// transmutations that shrink the size of the value; e.g.:
44 ///
45 /// ```
46 /// # use zerocopy::transmute;
47 /// let u: u32 = transmute!(#![allow(shrink)] 0u64);
48 /// assert_eq!(u, 0u32);
49 /// ```
50 ///
51 /// # Examples
52 ///
53 /// ```
54 /// # use zerocopy::transmute;
55 /// let one_dimensional: [u8; 8] = [0, 1, 2, 3, 4, 5, 6, 7];
56 ///
57 /// let two_dimensional: [[u8; 4]; 2] = transmute!(one_dimensional);
58 ///
59 /// assert_eq!(two_dimensional, [[0, 1, 2, 3], [4, 5, 6, 7]]);
60 /// ```
61 ///
62 /// # Use in `const` contexts
63 ///
64 /// This macro can be invoked in `const` contexts.
65 ///
66 #[doc = codegen_section!(
67     header = "h2",
68     bench = "transmute",
69     format = "coco_static_size",
70 )]
71 #[macro_export]
72 macro_rules! transmute {
73     // NOTE: This must be a macro (rather than a function with trait bounds)
74     // because there's no way, in a generic context, to enforce that two types
75     // have the same size. `core::mem::transmute` uses compiler magic to enforce
76     // this so long as the types are concrete.
77     (#![allow(shrink)] $e:expr) => {{
78         let mut e = $e;
79         if false {
80             // This branch, though never taken, ensures that the type of `e` is
81             // `IntoBytes` and that the type of the  outer macro invocation
82             // expression is `FromBytes`.
83 
84             fn transmute<Src, Dst>(src: Src) -> Dst
85             where
86                 Src: $crate::IntoBytes,
87                 Dst: $crate::FromBytes,
88             {
89                 let _ = src;
90                 loop {}
91             }
92             loop {}
93             #[allow(unreachable_code)]
94             transmute(e)
95         } else {
96             use $crate::util::macro_util::core_reexport::mem::ManuallyDrop;
97 
98             // NOTE: `repr(packed)` is important! It ensures that the size of
99             // `Transmute` won't be rounded up to accommodate `Src`'s or `Dst`'s
100             // alignment, which would break the size comparison logic below.
101             //
102             // As an example of why this is problematic, consider `Src = [u8;
103             // 5]`, `Dst = u32`. The total size of `Transmute<Src, Dst>` would
104             // be 8, and so we would reject a `[u8; 5]` to `u32` transmute as
105             // being size-increasing, which it isn't.
106             #[repr(C, packed)]
107             union Transmute<Src, Dst> {
108                 src: ManuallyDrop<Src>,
109                 dst: ManuallyDrop<Dst>,
110             }
111 
112             // SAFETY: `Transmute` is a `repr(C)` union whose `src` field has
113             // type `ManuallyDrop<Src>`. Thus, the `src` field starts at byte
114             // offset 0 within `Transmute` [1]. `ManuallyDrop<T>` has the same
115             // layout and bit validity as `T`, so it is sound to transmute `Src`
116             // to `Transmute`.
117             //
118             // [1] https://doc.rust-lang.org/1.85.0/reference/type-layout.html#reprc-unions
119             //
120             // [2] Per https://doc.rust-lang.org/1.85.0/std/mem/struct.ManuallyDrop.html:
121             //
122             //   `ManuallyDrop<T>` is guaranteed to have the same layout and bit
123             //   validity as `T`
124             let u: Transmute<_, _> = unsafe {
125                 // Clippy: We can't annotate the types; this macro is designed
126                 // to infer the types from the calling context.
127                 #[allow(clippy::missing_transmute_annotations)]
128                 $crate::util::macro_util::core_reexport::mem::transmute(e)
129             };
130 
131             if false {
132                 // SAFETY: This code is never executed.
133                 e = ManuallyDrop::into_inner(unsafe { u.src });
134                 // Suppress the `unused_assignments` lint on the previous line.
135                 let _ = e;
136                 loop {}
137             } else {
138                 // SAFETY: Per the safety comment on `let u` above, the `dst`
139                 // field in `Transmute` starts at byte offset 0, and has the
140                 // same layout and bit validity as `Dst`.
141                 //
142                 // Transmuting `Src` to `Transmute<Src, Dst>` above using
143                 // `core::mem::transmute` ensures that `size_of::<Src>() ==
144                 // size_of::<Transmute<Src, Dst>>()`. A `#[repr(C, packed)]`
145                 // union has the maximum size of all of its fields [1], so this
146                 // is equivalent to `size_of::<Src>() >= size_of::<Dst>()`.
147                 //
148                 // The outer `if`'s `false` branch ensures that `Src: IntoBytes`
149                 // and `Dst: FromBytes`. This, combined with the size bound,
150                 // ensures that this transmute is sound.
151                 //
152                 // [1] Per https://doc.rust-lang.org/1.85.0/reference/type-layout.html#reprc-unions:
153                 //
154                 //   The union will have a size of the maximum size of all of
155                 //   its fields rounded to its alignment
156                 let dst = unsafe { u.dst };
157                 $crate::util::macro_util::must_use(ManuallyDrop::into_inner(dst))
158             }
159         }
160     }};
161     ($e:expr) => {{
162         let e = $e;
163         if false {
164             // This branch, though never taken, ensures that the type of `e` is
165             // `IntoBytes` and that the type of the  outer macro invocation
166             // expression is `FromBytes`.
167 
168             fn transmute<Src, Dst>(src: Src) -> Dst
169             where
170                 Src: $crate::IntoBytes,
171                 Dst: $crate::FromBytes,
172             {
173                 let _ = src;
174                 loop {}
175             }
176             loop {}
177             #[allow(unreachable_code)]
178             transmute(e)
179         } else {
180             // SAFETY: `core::mem::transmute` ensures that the type of `e` and
181             // the type of this macro invocation expression have the same size.
182             // We know this transmute is safe thanks to the `IntoBytes` and
183             // `FromBytes` bounds enforced by the `false` branch.
184             let u = unsafe {
185                 // Clippy: We can't annotate the types; this macro is designed
186                 // to infer the types from the calling context.
187                 #[allow(clippy::missing_transmute_annotations, unnecessary_transmutes)]
188                 $crate::util::macro_util::core_reexport::mem::transmute(e)
189             };
190             $crate::util::macro_util::must_use(u)
191         }
192     }};
193 }
194 
195 /// Safely transmutes a mutable or immutable reference of one type to an
196 /// immutable reference of another type of the same size and compatible
197 /// alignment.
198 ///
199 /// This macro behaves like an invocation of this function:
200 ///
201 /// ```ignore
202 /// fn transmute_ref<'src, 'dst, Src, Dst>(src: &'src Src) -> &'dst Dst
203 /// where
204 ///     'src: 'dst,
205 ///     Src: IntoBytes + Immutable + ?Sized,
206 ///     Dst: FromBytes + Immutable + ?Sized,
207 ///     align_of::<Src>() >= align_of::<Dst>(),
208 ///     size_compatible::<Src, Dst>(),
209 /// {
210 /// # /*
211 ///     ...
212 /// # */
213 /// }
214 /// ```
215 ///
216 /// The types `Src` and `Dst` are inferred from the calling context; they cannot
217 /// be explicitly specified in the macro invocation.
218 ///
219 /// # Size compatibility
220 ///
221 /// `transmute_ref!` supports transmuting between `Sized` types, between unsized
222 /// (i.e., `?Sized`) types, and from a `Sized` type to an unsized type. It
223 /// supports any transmutation that preserves the number of bytes of the
224 /// referent, even if doing so requires updating the metadata stored in an
225 /// unsized "fat" reference:
226 ///
227 /// ```
228 /// # use zerocopy::transmute_ref;
229 /// # use core::mem::size_of_val; // Not in the prelude on our MSRV
230 /// let src: &[[u8; 2]] = &[[0, 1], [2, 3]][..];
231 /// let dst: &[u8] = transmute_ref!(src);
232 ///
233 /// assert_eq!(src.len(), 2);
234 /// assert_eq!(dst.len(), 4);
235 /// assert_eq!(dst, [0, 1, 2, 3]);
236 /// assert_eq!(size_of_val(src), size_of_val(dst));
237 /// ```
238 ///
239 /// # Errors
240 ///
241 /// Violations of the alignment and size compatibility checks are detected
242 /// *after* the compiler performs monomorphization. This has two important
243 /// consequences.
244 ///
245 /// First, it means that generic code will *never* fail these conditions:
246 ///
247 /// ```
248 /// # use zerocopy::{transmute_ref, FromBytes, IntoBytes, Immutable};
249 /// fn transmute_ref<Src, Dst>(src: &Src) -> &Dst
250 /// where
251 ///     Src: IntoBytes + Immutable,
252 ///     Dst: FromBytes + Immutable,
253 /// {
254 ///     transmute_ref!(src)
255 /// }
256 /// ```
257 ///
258 /// Instead, failures will only be detected once generic code is instantiated
259 /// with concrete types:
260 ///
261 /// ```compile_fail,E0080
262 /// # use zerocopy::{transmute_ref, FromBytes, IntoBytes, Immutable};
263 /// #
264 /// # fn transmute_ref<Src, Dst>(src: &Src) -> &Dst
265 /// # where
266 /// #     Src: IntoBytes + Immutable,
267 /// #     Dst: FromBytes + Immutable,
268 /// # {
269 /// #     transmute_ref!(src)
270 /// # }
271 /// let src: &u16 = &0;
272 /// let dst: &u8 = transmute_ref(src);
273 /// ```
274 ///
275 /// Second, the fact that violations are detected after monomorphization means
276 /// that `cargo check` will usually not detect errors, even when types are
277 /// concrete. Instead, `cargo build` must be used to detect such errors.
278 ///
279 /// # Examples
280 ///
281 /// Transmuting between `Sized` types:
282 ///
283 /// ```
284 /// # use zerocopy::transmute_ref;
285 /// let one_dimensional: [u8; 8] = [0, 1, 2, 3, 4, 5, 6, 7];
286 ///
287 /// let two_dimensional: &[[u8; 4]; 2] = transmute_ref!(&one_dimensional);
288 ///
289 /// assert_eq!(two_dimensional, &[[0, 1, 2, 3], [4, 5, 6, 7]]);
290 /// ```
291 ///
292 /// Transmuting between unsized types:
293 ///
294 /// ```
295 /// # use {zerocopy::*, zerocopy_derive::*};
296 /// # type u16 = zerocopy::byteorder::native_endian::U16;
297 /// # type u32 = zerocopy::byteorder::native_endian::U32;
298 /// #[derive(KnownLayout, FromBytes, IntoBytes, Immutable)]
299 /// #[repr(C)]
300 /// struct SliceDst<T, U> {
301 ///     t: T,
302 ///     u: [U],
303 /// }
304 ///
305 /// type Src = SliceDst<u32, u16>;
306 /// type Dst = SliceDst<u16, u8>;
307 ///
308 /// let src = Src::ref_from_bytes(&[0, 1, 2, 3, 4, 5, 6, 7]).unwrap();
309 /// let dst: &Dst = transmute_ref!(src);
310 ///
311 /// assert_eq!(src.t.as_bytes(), [0, 1, 2, 3]);
312 /// assert_eq!(src.u.len(), 2);
313 /// assert_eq!(src.u.as_bytes(), [4, 5, 6, 7]);
314 ///
315 /// assert_eq!(dst.t.as_bytes(), [0, 1]);
316 /// assert_eq!(dst.u, [2, 3, 4, 5, 6, 7]);
317 /// ```
318 ///
319 /// # Use in `const` contexts
320 ///
321 /// This macro can be invoked in `const` contexts only when `Src: Sized` and
322 /// `Dst: Sized`.
323 ///
324 #[doc = codegen_section!(
325     header = "h2",
326     bench = "transmute_ref",
327     format = "coco",
328     arity = 2,
329     [
330         open
331         @index 1
332         @title "Sized"
333         @variant "static_size"
334     ],
335     [
336         @index 2
337         @title "Unsized"
338         @variant "dynamic_size"
339     ]
340 )]
341 #[macro_export]
342 macro_rules! transmute_ref {
343     ($e:expr) => {{
344         // NOTE: This must be a macro (rather than a function with trait bounds)
345         // because there's no way, in a generic context, to enforce that two
346         // types have the same size or alignment.
347 
348         // Ensure that the source type is a reference or a mutable reference
349         // (note that mutable references are implicitly reborrowed here).
350         let e: &_ = $e;
351 
352         #[allow(unused, clippy::diverging_sub_expression)]
353         if false {
354             // This branch, though never taken, ensures that the type of `e` is
355             // `&T` where `T: IntoBytes + Immutable`, and that the type of this
356             // macro expression is `&U` where `U: FromBytes + Immutable`.
357 
358             struct AssertSrcIsIntoBytes<'a, T: ?::core::marker::Sized + $crate::IntoBytes>(&'a T);
359             struct AssertSrcIsImmutable<'a, T: ?::core::marker::Sized + $crate::Immutable>(&'a T);
360             struct AssertDstIsFromBytes<'a, U: ?::core::marker::Sized + $crate::FromBytes>(&'a U);
361             struct AssertDstIsImmutable<'a, T: ?::core::marker::Sized + $crate::Immutable>(&'a T);
362 
363             let _ = AssertSrcIsIntoBytes(e);
364             let _ = AssertSrcIsImmutable(e);
365 
366             if true {
367                 #[allow(unused, unreachable_code)]
368                 let u = AssertDstIsFromBytes(loop {});
369                 u.0
370             } else {
371                 #[allow(unused, unreachable_code)]
372                 let u = AssertDstIsImmutable(loop {});
373                 u.0
374             }
375         } else {
376             use $crate::util::macro_util::TransmuteRefDst;
377             let t = $crate::util::macro_util::Wrap::new(e);
378 
379             if false {
380                 // This branch exists solely to force the compiler to infer the
381                 // type of `Dst` *before* it attempts to resolve the method call
382                 // to `transmute_ref` in the `else` branch.
383                 //
384                 // Without this, if `Src` is `Sized` but `Dst` is `!Sized`, the
385                 // compiler will eagerly select the inherent impl of
386                 // `transmute_ref` (which requires `Dst: Sized`) because inherent
387                 // methods take priority over trait methods. It does this before
388                 // it realizes `Dst` is `!Sized`, leading to a compile error when
389                 // it checks the bounds later.
390                 //
391                 // By calling this helper (which returns `&Dst`), we force `Dst`
392                 // to be fully resolved. By the time it gets to the `else`
393                 // branch, the compiler knows `Dst` is `!Sized`, properly
394                 // disqualifies the inherent method, and falls back to the trait
395                 // implementation.
396                 t.transmute_ref_inference_helper()
397             } else {
398                 // SAFETY: The outer `if false` branch ensures that:
399                 // - `Src: IntoBytes + Immutable`
400                 // - `Dst: FromBytes + Immutable`
401                 unsafe {
402                     t.transmute_ref()
403                 }
404             }
405         }
406     }}
407 }
408 
409 /// Safely transmutes a mutable reference of one type to a mutable reference of
410 /// another type of the same size and compatible alignment.
411 ///
412 /// This macro behaves like an invocation of this function:
413 ///
414 /// ```ignore
415 /// const fn transmute_mut<'src, 'dst, Src, Dst>(src: &'src mut Src) -> &'dst mut Dst
416 /// where
417 ///     'src: 'dst,
418 ///     Src: FromBytes + IntoBytes + ?Sized,
419 ///     Dst: FromBytes + IntoBytes + ?Sized,
420 ///     align_of::<Src>() >= align_of::<Dst>(),
421 ///     size_compatible::<Src, Dst>(),
422 /// {
423 /// # /*
424 ///     ...
425 /// # */
426 /// }
427 /// ```
428 ///
429 /// The types `Src` and `Dst` are inferred from the calling context; they cannot
430 /// be explicitly specified in the macro invocation.
431 ///
432 /// # Size compatibility
433 ///
434 /// `transmute_mut!` supports transmuting between `Sized` types, between unsized
435 /// (i.e., `?Sized`) types, and from a `Sized` type to an unsized type. It
436 /// supports any transmutation that preserves the number of bytes of the
437 /// referent, even if doing so requires updating the metadata stored in an
438 /// unsized "fat" reference:
439 ///
440 /// ```
441 /// # use zerocopy::transmute_mut;
442 /// # use core::mem::size_of_val; // Not in the prelude on our MSRV
443 /// let src: &mut [[u8; 2]] = &mut [[0, 1], [2, 3]][..];
444 /// let dst: &mut [u8] = transmute_mut!(src);
445 ///
446 /// assert_eq!(dst.len(), 4);
447 /// assert_eq!(dst, [0, 1, 2, 3]);
448 /// let dst_size = size_of_val(dst);
449 /// assert_eq!(src.len(), 2);
450 /// assert_eq!(size_of_val(src), dst_size);
451 /// ```
452 ///
453 /// # Errors
454 ///
455 /// Violations of the alignment and size compatibility checks are detected
456 /// *after* the compiler performs monomorphization. This has two important
457 /// consequences.
458 ///
459 /// First, it means that generic code will *never* fail these conditions:
460 ///
461 /// ```
462 /// # use zerocopy::{transmute_mut, FromBytes, IntoBytes, Immutable};
463 /// fn transmute_mut<Src, Dst>(src: &mut Src) -> &mut Dst
464 /// where
465 ///     Src: FromBytes + IntoBytes,
466 ///     Dst: FromBytes + IntoBytes,
467 /// {
468 ///     transmute_mut!(src)
469 /// }
470 /// ```
471 ///
472 /// Instead, failures will only be detected once generic code is instantiated
473 /// with concrete types:
474 ///
475 /// ```compile_fail,E0080
476 /// # use zerocopy::{transmute_mut, FromBytes, IntoBytes, Immutable};
477 /// #
478 /// # fn transmute_mut<Src, Dst>(src: &mut Src) -> &mut Dst
479 /// # where
480 /// #     Src: FromBytes + IntoBytes,
481 /// #     Dst: FromBytes + IntoBytes,
482 /// # {
483 /// #     transmute_mut!(src)
484 /// # }
485 /// let src: &mut u16 = &mut 0;
486 /// let dst: &mut u8 = transmute_mut(src);
487 /// ```
488 ///
489 /// Second, the fact that violations are detected after monomorphization means
490 /// that `cargo check` will usually not detect errors, even when types are
491 /// concrete. Instead, `cargo build` must be used to detect such errors.
492 ///
493 ///
494 /// # Examples
495 ///
496 /// Transmuting between `Sized` types:
497 ///
498 /// ```
499 /// # use zerocopy::transmute_mut;
500 /// let mut one_dimensional: [u8; 8] = [0, 1, 2, 3, 4, 5, 6, 7];
501 ///
502 /// let two_dimensional: &mut [[u8; 4]; 2] = transmute_mut!(&mut one_dimensional);
503 ///
504 /// assert_eq!(two_dimensional, &[[0, 1, 2, 3], [4, 5, 6, 7]]);
505 ///
506 /// two_dimensional.reverse();
507 ///
508 /// assert_eq!(one_dimensional, [4, 5, 6, 7, 0, 1, 2, 3]);
509 /// ```
510 ///
511 /// Transmuting between unsized types:
512 ///
513 /// ```
514 /// # use {zerocopy::*, zerocopy_derive::*};
515 /// # type u16 = zerocopy::byteorder::native_endian::U16;
516 /// # type u32 = zerocopy::byteorder::native_endian::U32;
517 /// #[derive(KnownLayout, FromBytes, IntoBytes, Immutable)]
518 /// #[repr(C)]
519 /// struct SliceDst<T, U> {
520 ///     t: T,
521 ///     u: [U],
522 /// }
523 ///
524 /// type Src = SliceDst<u32, u16>;
525 /// type Dst = SliceDst<u16, u8>;
526 ///
527 /// let mut bytes = [0, 1, 2, 3, 4, 5, 6, 7];
528 /// let src = Src::mut_from_bytes(&mut bytes[..]).unwrap();
529 /// let dst: &mut Dst = transmute_mut!(src);
530 ///
531 /// assert_eq!(dst.t.as_bytes(), [0, 1]);
532 /// assert_eq!(dst.u, [2, 3, 4, 5, 6, 7]);
533 ///
534 /// assert_eq!(src.t.as_bytes(), [0, 1, 2, 3]);
535 /// assert_eq!(src.u.len(), 2);
536 /// assert_eq!(src.u.as_bytes(), [4, 5, 6, 7]);
537 /// ```
538 #[macro_export]
539 macro_rules! transmute_mut {
540     ($e:expr) => {{
541         // NOTE: This must be a macro (rather than a function with trait bounds)
542         // because, for backwards-compatibility on v0.8.x, we use the autoref
543         // specialization trick to dispatch to different `transmute_mut`
544         // implementations: one which doesn't require `Src: KnownLayout + Dst:
545         // KnownLayout` when `Src: Sized + Dst: Sized`, and one which requires
546         // `KnownLayout` bounds otherwise.
547 
548         // Ensure that the source type is a mutable reference.
549         let e: &mut _ = $e;
550 
551         #[allow(unused)]
552         use $crate::util::macro_util::TransmuteMutDst as _;
553         let t = $crate::util::macro_util::Wrap::new(e);
554         if false {
555             // This branch exists solely to force the compiler to infer the type
556             // of `Dst` *before* it attempts to resolve the method call to
557             // `transmute_mut` in the `else` branch.
558             //
559             // Without this, if `Src` is `Sized` but `Dst` is `!Sized`, the
560             // compiler will eagerly select the inherent impl of `transmute_mut`
561             // (which requires `Dst: Sized`) because inherent methods take
562             // priority over trait methods. It does this before it realizes
563             // `Dst` is `!Sized`, leading to a compile error when it checks the
564             // bounds later.
565             //
566             // By calling this helper (which returns `&mut Dst`), we force `Dst`
567             // to be fully resolved. By the time it gets to the `else` branch,
568             // the compiler knows `Dst` is `!Sized`, properly disqualifies the
569             // inherent method, and falls back to the trait implementation.
570             t.transmute_mut_inference_helper()
571         } else {
572             t.transmute_mut()
573         }
574     }}
575 }
576 
577 /// Conditionally transmutes a value of one type to a value of another type of
578 /// the same size.
579 ///
580 /// This macro behaves like an invocation of this function:
581 ///
582 /// ```ignore
583 /// fn try_transmute<Src, Dst>(src: Src) -> Result<Dst, ValidityError<Src, Dst>>
584 /// where
585 ///     Src: IntoBytes,
586 ///     Dst: TryFromBytes,
587 ///     size_of::<Src>() == size_of::<Dst>(),
588 /// {
589 /// # /*
590 ///     ...
591 /// # */
592 /// }
593 /// ```
594 ///
595 /// However, unlike a function, this macro can only be invoked when the types of
596 /// `Src` and `Dst` are completely concrete. The types `Src` and `Dst` are
597 /// inferred from the calling context; they cannot be explicitly specified in
598 /// the macro invocation.
599 ///
600 /// Note that the `Src` produced by the expression `$e` will *not* be dropped.
601 /// Semantically, its bits will be copied into a new value of type `Dst`, the
602 /// original `Src` will be forgotten, and the value of type `Dst` will be
603 /// returned.
604 ///
605 /// # Examples
606 ///
607 /// ```
608 /// # use zerocopy::*;
609 /// // 0u8 → bool = false
610 /// assert_eq!(try_transmute!(0u8), Ok(false));
611 ///
612 /// // 1u8 → bool = true
613 ///  assert_eq!(try_transmute!(1u8), Ok(true));
614 ///
615 /// // 2u8 → bool = error
616 /// assert!(matches!(
617 ///     try_transmute!(2u8),
618 ///     Result::<bool, _>::Err(ValidityError { .. })
619 /// ));
620 /// ```
621 ///
622 #[doc = codegen_section!(
623     header = "h2",
624     bench = "try_transmute",
625     format = "coco_static_size",
626 )]
627 #[macro_export]
628 macro_rules! try_transmute {
629     ($e:expr) => {{
630         // NOTE: This must be a macro (rather than a function with trait bounds)
631         // because there's no way, in a generic context, to enforce that two
632         // types have the same size. `core::mem::transmute` uses compiler magic
633         // to enforce this so long as the types are concrete.
634 
635         let e = $e;
636         if false {
637             // Check that the sizes of the source and destination types are
638             // equal.
639 
640             // SAFETY: This code is never executed.
641             Ok(unsafe {
642                 // Clippy: We can't annotate the types; this macro is designed
643                 // to infer the types from the calling context.
644                 #[allow(clippy::missing_transmute_annotations)]
645                 $crate::util::macro_util::core_reexport::mem::transmute(e)
646             })
647         } else {
648             $crate::util::macro_util::try_transmute::<_, _>(e)
649         }
650     }}
651 }
652 
653 /// Conditionally transmutes a mutable or immutable reference of one type to an
654 /// immutable reference of another type of the same size and compatible
655 /// alignment.
656 ///
657 /// *Note that while the **value** of the referent is checked for validity at
658 /// runtime, the **size** and **alignment** are checked at compile time. For
659 /// conversions which are fallible with respect to size and alignment, see the
660 /// methods on [`TryFromBytes`].*
661 ///
662 /// This macro behaves like an invocation of this function:
663 ///
664 /// ```ignore
665 /// fn try_transmute_ref<Src, Dst>(src: &Src) -> Result<&Dst, ValidityError<&Src, Dst>>
666 /// where
667 ///     Src: IntoBytes + Immutable + ?Sized,
668 ///     Dst: TryFromBytes + Immutable + ?Sized,
669 ///     align_of::<Src>() >= align_of::<Dst>(),
670 ///     size_compatible::<Src, Dst>(),
671 /// {
672 /// # /*
673 ///     ...
674 /// # */
675 /// }
676 /// ```
677 ///
678 /// The types `Src` and `Dst` are inferred from the calling context; they cannot
679 /// be explicitly specified in the macro invocation.
680 ///
681 /// [`TryFromBytes`]: crate::TryFromBytes
682 ///
683 /// # Size compatibility
684 ///
685 /// `try_transmute_ref!` supports transmuting between `Sized` types, between
686 /// unsized (i.e., `?Sized`) types, and from a `Sized` type to an unsized type.
687 /// It supports any transmutation that preserves the number of bytes of the
688 /// referent, even if doing so requires updating the metadata stored in an
689 /// unsized "fat" reference:
690 ///
691 /// ```
692 /// # use zerocopy::try_transmute_ref;
693 /// # use core::mem::size_of_val; // Not in the prelude on our MSRV
694 /// let src: &[[u8; 2]] = &[[0, 1], [2, 3]][..];
695 /// let dst: &[u8] = try_transmute_ref!(src).unwrap();
696 ///
697 /// assert_eq!(src.len(), 2);
698 /// assert_eq!(dst.len(), 4);
699 /// assert_eq!(dst, [0, 1, 2, 3]);
700 /// assert_eq!(size_of_val(src), size_of_val(dst));
701 /// ```
702 ///
703 /// # Examples
704 ///
705 /// Transmuting between `Sized` types:
706 ///
707 /// ```
708 /// # use zerocopy::*;
709 /// // 0u8 → bool = false
710 /// assert_eq!(try_transmute_ref!(&0u8), Ok(&false));
711 ///
712 /// // 1u8 → bool = true
713 ///  assert_eq!(try_transmute_ref!(&1u8), Ok(&true));
714 ///
715 /// // 2u8 → bool = error
716 /// assert!(matches!(
717 ///     try_transmute_ref!(&2u8),
718 ///     Result::<&bool, _>::Err(ValidityError { .. })
719 /// ));
720 /// ```
721 ///
722 /// Transmuting between unsized types:
723 ///
724 /// ```
725 /// # use {zerocopy::*, zerocopy_derive::*};
726 /// # type u16 = zerocopy::byteorder::native_endian::U16;
727 /// # type u32 = zerocopy::byteorder::native_endian::U32;
728 /// #[derive(KnownLayout, FromBytes, IntoBytes, Immutable)]
729 /// #[repr(C)]
730 /// struct SliceDst<T, U> {
731 ///     t: T,
732 ///     u: [U],
733 /// }
734 ///
735 /// type Src = SliceDst<u32, u16>;
736 /// type Dst = SliceDst<u16, bool>;
737 ///
738 /// let src = Src::ref_from_bytes(&[0, 1, 0, 1, 0, 1, 0, 1]).unwrap();
739 /// let dst: &Dst = try_transmute_ref!(src).unwrap();
740 ///
741 /// assert_eq!(src.t.as_bytes(), [0, 1, 0, 1]);
742 /// assert_eq!(src.u.len(), 2);
743 /// assert_eq!(src.u.as_bytes(), [0, 1, 0, 1]);
744 ///
745 /// assert_eq!(dst.t.as_bytes(), [0, 1]);
746 /// assert_eq!(dst.u, [false, true, false, true, false, true]);
747 /// ```
748 ///
749 #[doc = codegen_section!(
750     header = "h2",
751     bench = "try_transmute_ref",
752     format = "coco",
753     arity = 2,
754     [
755         open
756         @index 1
757         @title "Sized"
758         @variant "static_size"
759     ],
760     [
761         @index 2
762         @title "Unsized"
763         @variant "dynamic_size"
764     ]
765 )]
766 #[macro_export]
767 macro_rules! try_transmute_ref {
768     ($e:expr) => {{
769         // Ensure that the source type is a reference or a mutable reference
770         // (note that mutable references are implicitly reborrowed here).
771         let e: &_ = $e;
772 
773         #[allow(unused_imports)]
774         use $crate::util::macro_util::TryTransmuteRefDst as _;
775         let t = $crate::util::macro_util::Wrap::new(e);
776         if false {
777             // This branch exists solely to force the compiler to infer the type
778             // of `Dst` *before* it attempts to resolve the method call to
779             // `try_transmute_ref` in the `else` branch.
780             //
781             // Without this, if `Src` is `Sized` but `Dst` is `!Sized`, the
782             // compiler will eagerly select the inherent impl of
783             // `try_transmute_ref` (which requires `Dst: Sized`) because
784             // inherent methods take priority over trait methods. It does this
785             // before it realizes `Dst` is `!Sized`, leading to a compile error
786             // when it checks the bounds later.
787             //
788             // By calling this helper (which returns `&Dst`), we force `Dst`
789             // to be fully resolved. By the time it gets to the `else`
790             // branch, the compiler knows `Dst` is `!Sized`, properly
791             // disqualifies the inherent method, and falls back to the trait
792             // implementation.
793             Ok(t.transmute_ref_inference_helper())
794         } else {
795             t.try_transmute_ref()
796         }
797     }}
798 }
799 
800 /// Conditionally transmutes a mutable reference of one type to a mutable
801 /// reference of another type of the same size and compatible alignment.
802 ///
803 /// *Note that while the **value** of the referent is checked for validity at
804 /// runtime, the **size** and **alignment** are checked at compile time. For
805 /// conversions which are fallible with respect to size and alignment, see the
806 /// methods on [`TryFromBytes`].*
807 ///
808 /// This macro behaves like an invocation of this function:
809 ///
810 /// ```ignore
811 /// fn try_transmute_mut<Src, Dst>(src: &mut Src) -> Result<&mut Dst, ValidityError<&mut Src, Dst>>
812 /// where
813 ///     Src: FromBytes + IntoBytes + ?Sized,
814 ///     Dst: TryFromBytes + IntoBytes + ?Sized,
815 ///     align_of::<Src>() >= align_of::<Dst>(),
816 ///     size_compatible::<Src, Dst>(),
817 /// {
818 /// # /*
819 ///     ...
820 /// # */
821 /// }
822 /// ```
823 ///
824 /// The types `Src` and `Dst` are inferred from the calling context; they cannot
825 /// be explicitly specified in the macro invocation.
826 ///
827 /// [`TryFromBytes`]: crate::TryFromBytes
828 ///
829 /// # Size compatibility
830 ///
831 /// `try_transmute_mut!` supports transmuting between `Sized` types, between
832 /// unsized (i.e., `?Sized`) types, and from a `Sized` type to an unsized type.
833 /// It supports any transmutation that preserves the number of bytes of the
834 /// referent, even if doing so requires updating the metadata stored in an
835 /// unsized "fat" reference:
836 ///
837 /// ```
838 /// # use zerocopy::try_transmute_mut;
839 /// # use core::mem::size_of_val; // Not in the prelude on our MSRV
840 /// let src: &mut [[u8; 2]] = &mut [[0, 1], [2, 3]][..];
841 /// let dst: &mut [u8] = try_transmute_mut!(src).unwrap();
842 ///
843 /// assert_eq!(dst.len(), 4);
844 /// assert_eq!(dst, [0, 1, 2, 3]);
845 /// let dst_size = size_of_val(dst);
846 /// assert_eq!(src.len(), 2);
847 /// assert_eq!(size_of_val(src), dst_size);
848 /// ```
849 ///
850 /// # Examples
851 ///
852 /// Transmuting between `Sized` types:
853 ///
854 /// ```
855 /// # use zerocopy::*;
856 /// // 0u8 → bool = false
857 /// let src = &mut 0u8;
858 /// assert_eq!(try_transmute_mut!(src), Ok(&mut false));
859 ///
860 /// // 1u8 → bool = true
861 /// let src = &mut 1u8;
862 ///  assert_eq!(try_transmute_mut!(src), Ok(&mut true));
863 ///
864 /// // 2u8 → bool = error
865 /// let src = &mut 2u8;
866 /// assert!(matches!(
867 ///     try_transmute_mut!(src),
868 ///     Result::<&mut bool, _>::Err(ValidityError { .. })
869 /// ));
870 /// ```
871 ///
872 /// Transmuting between unsized types:
873 ///
874 /// ```
875 /// # use {zerocopy::*, zerocopy_derive::*};
876 /// # type u16 = zerocopy::byteorder::native_endian::U16;
877 /// # type u32 = zerocopy::byteorder::native_endian::U32;
878 /// #[derive(KnownLayout, FromBytes, IntoBytes, Immutable)]
879 /// #[repr(C)]
880 /// struct SliceDst<T, U> {
881 ///     t: T,
882 ///     u: [U],
883 /// }
884 ///
885 /// type Src = SliceDst<u32, u16>;
886 /// type Dst = SliceDst<u16, bool>;
887 ///
888 /// let mut bytes = [0, 1, 0, 1, 0, 1, 0, 1];
889 /// let src = Src::mut_from_bytes(&mut bytes).unwrap();
890 ///
891 /// assert_eq!(src.t.as_bytes(), [0, 1, 0, 1]);
892 /// assert_eq!(src.u.len(), 2);
893 /// assert_eq!(src.u.as_bytes(), [0, 1, 0, 1]);
894 ///
895 /// let dst: &Dst = try_transmute_mut!(src).unwrap();
896 ///
897 /// assert_eq!(dst.t.as_bytes(), [0, 1]);
898 /// assert_eq!(dst.u, [false, true, false, true, false, true]);
899 /// ```
900 #[macro_export]
901 macro_rules! try_transmute_mut {
902     ($e:expr) => {{
903         // Ensure that the source type is a mutable reference.
904         let e: &mut _ = $e;
905 
906         #[allow(unused_imports)]
907         use $crate::util::macro_util::TryTransmuteMutDst as _;
908         let t = $crate::util::macro_util::Wrap::new(e);
909         if false {
910             // This branch exists solely to force the compiler to infer the type
911             // of `Dst` *before* it attempts to resolve the method call to
912             // `try_transmute_mut` in the `else` branch.
913             //
914             // Without this, if `Src` is `Sized` but `Dst` is `!Sized`, the
915             // compiler will eagerly select the inherent impl of
916             // `try_transmute_mut` (which requires `Dst: Sized`) because
917             // inherent methods take priority over trait methods. It does this
918             // before it realizes `Dst` is `!Sized`, leading to a compile error
919             // when it checks the bounds later.
920             //
921             // By calling this helper (which returns `&Dst`), we force `Dst`
922             // to be fully resolved. By the time it gets to the `else`
923             // branch, the compiler knows `Dst` is `!Sized`, properly
924             // disqualifies the inherent method, and falls back to the trait
925             // implementation.
926             Ok(t.transmute_mut_inference_helper())
927         } else {
928             t.try_transmute_mut()
929         }
930     }}
931 }
932 
933 /// Includes a file and safely transmutes it to a value of an arbitrary type.
934 ///
935 /// The file will be included as a byte array, `[u8; N]`, which will be
936 /// transmuted to another type, `T`. `T` is inferred from the calling context,
937 /// and must implement [`FromBytes`].
938 ///
939 /// The file is located relative to the current file (similarly to how modules
940 /// are found). The provided path is interpreted in a platform-specific way at
941 /// compile time. So, for instance, an invocation with a Windows path containing
942 /// backslashes `\` would not compile correctly on Unix.
943 ///
944 /// `include_value!` is ignorant of byte order. For byte order-aware types, see
945 /// the [`byteorder`] module.
946 ///
947 /// [`FromBytes`]: crate::FromBytes
948 /// [`byteorder`]: crate::byteorder
949 ///
950 /// # Examples
951 ///
952 /// Assume there are two files in the same directory with the following
953 /// contents:
954 ///
955 /// File `data` (no trailing newline):
956 ///
957 /// ```text
958 /// abcd
959 /// ```
960 ///
961 /// File `main.rs`:
962 ///
963 /// ```rust
964 /// use zerocopy::include_value;
965 /// # macro_rules! include_value {
966 /// # ($file:expr) => { zerocopy::include_value!(concat!("../testdata/include_value/", $file)) };
967 /// # }
968 ///
969 /// fn main() {
970 ///     let as_u32: u32 = include_value!("data");
971 ///     assert_eq!(as_u32, u32::from_ne_bytes([b'a', b'b', b'c', b'd']));
972 ///     let as_i32: i32 = include_value!("data");
973 ///     assert_eq!(as_i32, i32::from_ne_bytes([b'a', b'b', b'c', b'd']));
974 /// }
975 /// ```
976 ///
977 /// # Use in `const` contexts
978 ///
979 /// This macro can be invoked in `const` contexts.
980 #[doc(alias("include_bytes", "include_data", "include_type"))]
981 #[macro_export]
982 macro_rules! include_value {
983     ($file:expr $(,)?) => {
984         $crate::transmute!(*::core::include_bytes!($file))
985     };
986 }
987 
988 #[doc(hidden)]
989 #[macro_export]
990 macro_rules! cryptocorrosion_derive_traits {
991     (
992         #[repr($repr:ident)]
993         $(#[$attr:meta])*
994         $vis:vis struct $name:ident $(<$($tyvar:ident),*>)?
995         $(
996             (
997                 $($tuple_field_vis:vis $tuple_field_ty:ty),*
998             );
999         )?
1000 
1001         $(
1002             {
1003                 $($field_vis:vis $field_name:ident: $field_ty:ty,)*
1004             }
1005         )?
1006     ) => {
1007         $crate::cryptocorrosion_derive_traits!(@assert_allowed_struct_repr #[repr($repr)]);
1008 
1009         $(#[$attr])*
1010         #[repr($repr)]
1011         $vis struct $name $(<$($tyvar),*>)?
1012         $(
1013             (
1014                 $($tuple_field_vis $tuple_field_ty),*
1015             );
1016         )?
1017 
1018         $(
1019             {
1020                 $($field_vis $field_name: $field_ty,)*
1021             }
1022         )?
1023 
1024         // SAFETY: See inline.
1025         unsafe impl $(<$($tyvar),*>)? $crate::TryFromBytes for $name$(<$($tyvar),*>)?
1026         where
1027             $(
1028                 $($tuple_field_ty: $crate::FromBytes,)*
1029             )?
1030 
1031             $(
1032                 $($field_ty: $crate::FromBytes,)*
1033             )?
1034         {
1035             #[inline(always)]
1036             fn is_bit_valid<A>(_: $crate::Maybe<'_, Self, A>) -> bool
1037             where
1038                 A: $crate::invariant::Alignment,
1039             {
1040                 // SAFETY: This macro only accepts `#[repr(C)]` and
1041                 // `#[repr(transparent)]` structs, and this `impl` block
1042                 // requires all field types to be `FromBytes`. Thus, all
1043                 // initialized byte sequences constitutes valid instances of
1044                 // `Self`.
1045                 true
1046             }
1047 
1048             fn only_derive_is_allowed_to_implement_this_trait() {}
1049         }
1050 
1051         // SAFETY: This macro only accepts `#[repr(C)]` and
1052         // `#[repr(transparent)]` structs, and this `impl` block requires all
1053         // field types to be `FromBytes`, which is a sub-trait of `FromZeros`.
1054         unsafe impl $(<$($tyvar),*>)? $crate::FromZeros for $name$(<$($tyvar),*>)?
1055         where
1056             $(
1057                 $($tuple_field_ty: $crate::FromBytes,)*
1058             )?
1059 
1060             $(
1061                 $($field_ty: $crate::FromBytes,)*
1062             )?
1063         {
1064             fn only_derive_is_allowed_to_implement_this_trait() {}
1065         }
1066 
1067         // SAFETY: This macro only accepts `#[repr(C)]` and
1068         // `#[repr(transparent)]` structs, and this `impl` block requires all
1069         // field types to be `FromBytes`.
1070         unsafe impl $(<$($tyvar),*>)? $crate::FromBytes for $name$(<$($tyvar),*>)?
1071         where
1072             $(
1073                 $($tuple_field_ty: $crate::FromBytes,)*
1074             )?
1075 
1076             $(
1077                 $($field_ty: $crate::FromBytes,)*
1078             )?
1079         {
1080             fn only_derive_is_allowed_to_implement_this_trait() {}
1081         }
1082 
1083         // SAFETY: This macro only accepts `#[repr(C)]` and
1084         // `#[repr(transparent)]` structs, this `impl` block requires all field
1085         // types to be `IntoBytes`, and a padding check is used to ensures that
1086         // there are no padding bytes.
1087         unsafe impl $(<$($tyvar),*>)? $crate::IntoBytes for $name$(<$($tyvar),*>)?
1088         where
1089             $(
1090                 $($tuple_field_ty: $crate::IntoBytes,)*
1091             )?
1092 
1093             $(
1094                 $($field_ty: $crate::IntoBytes,)*
1095             )?
1096 
1097             (): $crate::util::macro_util::PaddingFree<
1098                 Self,
1099                 {
1100                     $crate::cryptocorrosion_derive_traits!(
1101                         @struct_padding_check #[repr($repr)]
1102                         $(($($tuple_field_ty),*))?
1103                         $({$($field_ty),*})?
1104                     )
1105                 },
1106             >,
1107         {
1108             fn only_derive_is_allowed_to_implement_this_trait() {}
1109         }
1110 
1111         // SAFETY: This macro only accepts `#[repr(C)]` and
1112         // `#[repr(transparent)]` structs, and this `impl` block requires all
1113         // field types to be `Immutable`.
1114         unsafe impl $(<$($tyvar),*>)? $crate::Immutable for $name$(<$($tyvar),*>)?
1115         where
1116             $(
1117                 $($tuple_field_ty: $crate::Immutable,)*
1118             )?
1119 
1120             $(
1121                 $($field_ty: $crate::Immutable,)*
1122             )?
1123         {
1124             fn only_derive_is_allowed_to_implement_this_trait() {}
1125         }
1126     };
1127     (@assert_allowed_struct_repr #[repr(transparent)]) => {};
1128     (@assert_allowed_struct_repr #[repr(C)]) => {};
1129     (@assert_allowed_struct_repr #[$_attr:meta]) => {
1130         compile_error!("repr must be `#[repr(transparent)]` or `#[repr(C)]`");
1131     };
1132     (
1133         @struct_padding_check #[repr(transparent)]
1134         $(($($tuple_field_ty:ty),*))?
1135         $({$($field_ty:ty),*})?
1136     ) => {
1137         // SAFETY: `#[repr(transparent)]` structs cannot have the same layout as
1138         // their single non-zero-sized field, and so cannot have any padding
1139         // outside of that field.
1140         0
1141     };
1142     (
1143         @struct_padding_check #[repr(C)]
1144         $(($($tuple_field_ty:ty),*))?
1145         $({$($field_ty:ty),*})?
1146     ) => {
1147         $crate::struct_padding!(
1148             Self,
1149             None,
1150             None,
1151             [
1152                 $($($tuple_field_ty),*)?
1153                 $($($field_ty),*)?
1154             ]
1155         )
1156     };
1157     (
1158         #[repr(C)]
1159         $(#[$attr:meta])*
1160         $vis:vis union $name:ident {
1161             $(
1162                 $field_name:ident: $field_ty:ty,
1163             )*
1164         }
1165     ) => {
1166         $(#[$attr])*
1167         #[repr(C)]
1168         $vis union $name {
1169             $(
1170                 $field_name: $field_ty,
1171             )*
1172         }
1173 
1174         // SAFETY: See inline.
1175         unsafe impl $crate::TryFromBytes for $name
1176         where
1177             $(
1178                 $field_ty: $crate::FromBytes,
1179             )*
1180         {
1181             #[inline(always)]
1182             fn is_bit_valid<A>(_: $crate::Maybe<'_, Self, A>) -> bool
1183             where
1184                 A: $crate::invariant::Alignment,
1185             {
1186                 // SAFETY: This macro only accepts `#[repr(C)]` unions, and this
1187                 // `impl` block requires all field types to be `FromBytes`.
1188                 // Thus, all initialized byte sequences constitutes valid
1189                 // instances of `Self`.
1190                 true
1191             }
1192 
1193             fn only_derive_is_allowed_to_implement_this_trait() {}
1194         }
1195 
1196         // SAFETY: This macro only accepts `#[repr(C)]` unions, and this `impl`
1197         // block requires all field types to be `FromBytes`, which is a
1198         // sub-trait of `FromZeros`.
1199         unsafe impl $crate::FromZeros for $name
1200         where
1201             $(
1202                 $field_ty: $crate::FromBytes,
1203             )*
1204         {
1205             fn only_derive_is_allowed_to_implement_this_trait() {}
1206         }
1207 
1208         // SAFETY: This macro only accepts `#[repr(C)]` unions, and this `impl`
1209         // block requires all field types to be `FromBytes`.
1210         unsafe impl $crate::FromBytes for $name
1211         where
1212             $(
1213                 $field_ty: $crate::FromBytes,
1214             )*
1215         {
1216             fn only_derive_is_allowed_to_implement_this_trait() {}
1217         }
1218 
1219         // SAFETY: This macro only accepts `#[repr(C)]` unions, this `impl`
1220         // block requires all field types to be `IntoBytes`, and a padding check
1221         // is used to ensures that there are no padding bytes before or after
1222         // any field.
1223         unsafe impl $crate::IntoBytes for $name
1224         where
1225             $(
1226                 $field_ty: $crate::IntoBytes,
1227             )*
1228             (): $crate::util::macro_util::PaddingFree<
1229                 Self,
1230                 {
1231                     $crate::union_padding!(
1232                         Self,
1233                         None::<usize>,
1234                         None::<usize>,
1235                         [$($field_ty),*]
1236                     )
1237                 },
1238             >,
1239         {
1240             fn only_derive_is_allowed_to_implement_this_trait() {}
1241         }
1242 
1243         // SAFETY: This macro only accepts `#[repr(C)]` unions, and this `impl`
1244         // block requires all field types to be `Immutable`.
1245         unsafe impl $crate::Immutable for $name
1246         where
1247             $(
1248                 $field_ty: $crate::Immutable,
1249             )*
1250         {
1251             fn only_derive_is_allowed_to_implement_this_trait() {}
1252         }
1253     };
1254 }
1255 
1256 #[cfg(test)]
1257 mod tests {
1258     use crate::{
1259         byteorder::native_endian::{U16, U32},
1260         util::testutil::*,
1261         *,
1262     };
1263 
1264     #[derive(KnownLayout, Immutable, FromBytes, IntoBytes, PartialEq, Debug)]
1265     #[repr(C)]
1266     struct SliceDst<T, U> {
1267         a: T,
1268         b: [U],
1269     }
1270 
1271     #[test]
1272     fn test_transmute() {
1273         // Test that memory is transmuted as expected.
1274         let array_of_u8s = [0u8, 1, 2, 3, 4, 5, 6, 7];
1275         let array_of_arrays = [[0, 1], [2, 3], [4, 5], [6, 7]];
1276         let x: [[u8; 2]; 4] = transmute!(array_of_u8s);
1277         assert_eq!(x, array_of_arrays);
1278         let x: [u8; 8] = transmute!(array_of_arrays);
1279         assert_eq!(x, array_of_u8s);
1280 
1281         // Test that memory is transmuted as expected when shrinking.
1282         let x: [[u8; 2]; 3] = transmute!(#![allow(shrink)] array_of_u8s);
1283         assert_eq!(x, [[0u8, 1], [2, 3], [4, 5]]);
1284 
1285         // Test that the source expression's value is forgotten rather than
1286         // dropped.
1287         #[derive(IntoBytes)]
1288         #[repr(transparent)]
1289         struct PanicOnDrop(());
1290         impl Drop for PanicOnDrop {
1291             fn drop(&mut self) {
1292                 panic!("PanicOnDrop::drop");
1293             }
1294         }
1295         #[allow(clippy::let_unit_value)]
1296         let _: () = transmute!(PanicOnDrop(()));
1297         #[allow(clippy::let_unit_value)]
1298         let _: () = transmute!(#![allow(shrink)] PanicOnDrop(()));
1299 
1300         // Test that `transmute!` is legal in a const context.
1301         const ARRAY_OF_U8S: [u8; 8] = [0u8, 1, 2, 3, 4, 5, 6, 7];
1302         const ARRAY_OF_ARRAYS: [[u8; 2]; 4] = [[0, 1], [2, 3], [4, 5], [6, 7]];
1303         const X: [[u8; 2]; 4] = transmute!(ARRAY_OF_U8S);
1304         assert_eq!(X, ARRAY_OF_ARRAYS);
1305         const X_SHRINK: [[u8; 2]; 3] = transmute!(#![allow(shrink)] ARRAY_OF_U8S);
1306         assert_eq!(X_SHRINK, [[0u8, 1], [2, 3], [4, 5]]);
1307 
1308         // Test that `transmute!` works with `!Immutable` types.
1309         let x: usize = transmute!(UnsafeCell::new(1usize));
1310         assert_eq!(x, 1);
1311         let x: UnsafeCell<usize> = transmute!(1usize);
1312         assert_eq!(x.into_inner(), 1);
1313         let x: UnsafeCell<isize> = transmute!(UnsafeCell::new(1usize));
1314         assert_eq!(x.into_inner(), 1);
1315     }
1316 
1317     // A `Sized` type which doesn't implement `KnownLayout` (it is "not
1318     // `KnownLayout`", or `Nkl`).
1319     //
1320     // This permits us to test that `transmute_ref!` and `transmute_mut!` work
1321     // for types which are `Sized + !KnownLayout`. When we added support for
1322     // slice DSTs in #1924, this new support relied on `KnownLayout`, but we
1323     // need to make sure to remain backwards-compatible with code which uses
1324     // these macros with types which are `!KnownLayout`.
1325     #[derive(FromBytes, IntoBytes, Immutable, PartialEq, Eq, Debug)]
1326     #[repr(transparent)]
1327     struct Nkl<T>(T);
1328 
1329     #[test]
1330     fn test_transmute_ref() {
1331         // Test that memory is transmuted as expected.
1332         let array_of_u8s = [0u8, 1, 2, 3, 4, 5, 6, 7];
1333         let array_of_arrays = [[0, 1], [2, 3], [4, 5], [6, 7]];
1334         let x: &[[u8; 2]; 4] = transmute_ref!(&array_of_u8s);
1335         assert_eq!(*x, array_of_arrays);
1336         let x: &[u8; 8] = transmute_ref!(&array_of_arrays);
1337         assert_eq!(*x, array_of_u8s);
1338 
1339         // Test that `transmute_ref!` is legal in a const context.
1340         const ARRAY_OF_U8S: [u8; 8] = [0u8, 1, 2, 3, 4, 5, 6, 7];
1341         const ARRAY_OF_ARRAYS: [[u8; 2]; 4] = [[0, 1], [2, 3], [4, 5], [6, 7]];
1342         #[allow(clippy::redundant_static_lifetimes)]
1343         const X: &'static [[u8; 2]; 4] = transmute_ref!(&ARRAY_OF_U8S);
1344         assert_eq!(*X, ARRAY_OF_ARRAYS);
1345 
1346         // Test sized -> unsized transmutation.
1347         let array_of_u8s = [0u8, 1, 2, 3, 4, 5, 6, 7];
1348         let array_of_arrays = [[0, 1], [2, 3], [4, 5], [6, 7]];
1349         let slice_of_arrays = &array_of_arrays[..];
1350         let x: &[[u8; 2]] = transmute_ref!(&array_of_u8s);
1351         assert_eq!(x, slice_of_arrays);
1352 
1353         // Before 1.61.0, we can't define the `const fn transmute_ref` function
1354         // that we do on and after 1.61.0.
1355         #[cfg(no_zerocopy_generic_bounds_in_const_fn_1_61_0)]
1356         {
1357             // Test that `transmute_ref!` supports non-`KnownLayout` `Sized`
1358             // types.
1359             const ARRAY_OF_NKL_U8S: Nkl<[u8; 8]> = Nkl([0u8, 1, 2, 3, 4, 5, 6, 7]);
1360             const ARRAY_OF_NKL_ARRAYS: Nkl<[[u8; 2]; 4]> = Nkl([[0, 1], [2, 3], [4, 5], [6, 7]]);
1361             const X_NKL: &Nkl<[[u8; 2]; 4]> = transmute_ref!(&ARRAY_OF_NKL_U8S);
1362             assert_eq!(*X_NKL, ARRAY_OF_NKL_ARRAYS);
1363         }
1364 
1365         #[cfg(not(no_zerocopy_generic_bounds_in_const_fn_1_61_0))]
1366         {
1367             // Call through a generic function to make sure our autoref
1368             // specialization trick works even when types are generic.
1369             const fn transmute_ref<T, U>(t: &T) -> &U
1370             where
1371                 T: IntoBytes + Immutable,
1372                 U: FromBytes + Immutable,
1373             {
1374                 transmute_ref!(t)
1375             }
1376 
1377             // Test that `transmute_ref!` supports non-`KnownLayout` `Sized`
1378             // types.
1379             const ARRAY_OF_NKL_U8S: Nkl<[u8; 8]> = Nkl([0u8, 1, 2, 3, 4, 5, 6, 7]);
1380             const ARRAY_OF_NKL_ARRAYS: Nkl<[[u8; 2]; 4]> = Nkl([[0, 1], [2, 3], [4, 5], [6, 7]]);
1381             const X_NKL: &Nkl<[[u8; 2]; 4]> = transmute_ref(&ARRAY_OF_NKL_U8S);
1382             assert_eq!(*X_NKL, ARRAY_OF_NKL_ARRAYS);
1383         }
1384 
1385         // Test that `transmute_ref!` works on slice DSTs in and that memory is
1386         // transmuted as expected.
1387         let slice_dst_of_u8s =
1388             SliceDst::<U16, [u8; 2]>::ref_from_bytes(&[0, 1, 2, 3, 4, 5][..]).unwrap();
1389         let slice_dst_of_u16s =
1390             SliceDst::<U16, U16>::ref_from_bytes(&[0, 1, 2, 3, 4, 5][..]).unwrap();
1391         let x: &SliceDst<U16, U16> = transmute_ref!(slice_dst_of_u8s);
1392         assert_eq!(x, slice_dst_of_u16s);
1393 
1394         let slice_dst_of_u8s =
1395             SliceDst::<U16, u8>::ref_from_bytes(&[0, 1, 2, 3, 4, 5][..]).unwrap();
1396         let x: &[u8] = transmute_ref!(slice_dst_of_u8s);
1397         assert_eq!(x, [0, 1, 2, 3, 4, 5]);
1398 
1399         let x: &[u8] = transmute_ref!(slice_dst_of_u16s);
1400         assert_eq!(x, [0, 1, 2, 3, 4, 5]);
1401 
1402         let x: &[U16] = transmute_ref!(slice_dst_of_u16s);
1403         let slice_of_u16s: &[U16] = <[U16]>::ref_from_bytes(&[0, 1, 2, 3, 4, 5][..]).unwrap();
1404         assert_eq!(x, slice_of_u16s);
1405 
1406         // Test that transmuting from a type with larger trailing slice offset
1407         // and larger trailing slice element works.
1408         let bytes = &[0, 1, 2, 3, 4, 5, 6, 7][..];
1409         let slice_dst_big = SliceDst::<U32, U16>::ref_from_bytes(bytes).unwrap();
1410         let slice_dst_small = SliceDst::<U16, u8>::ref_from_bytes(bytes).unwrap();
1411         let x: &SliceDst<U16, u8> = transmute_ref!(slice_dst_big);
1412         assert_eq!(x, slice_dst_small);
1413 
1414         // Test that it's legal to transmute a reference while shrinking the
1415         // lifetime (note that `X` has the lifetime `'static`).
1416         let x: &[u8; 8] = transmute_ref!(X);
1417         assert_eq!(*x, ARRAY_OF_U8S);
1418 
1419         // Test that `transmute_ref!` supports decreasing alignment.
1420         let u = AU64(0);
1421         let array = [0, 0, 0, 0, 0, 0, 0, 0];
1422         let x: &[u8; 8] = transmute_ref!(&u);
1423         assert_eq!(*x, array);
1424 
1425         // Test that a mutable reference can be turned into an immutable one.
1426         let mut x = 0u8;
1427         #[allow(clippy::useless_transmute)]
1428         let y: &u8 = transmute_ref!(&mut x);
1429         assert_eq!(*y, 0);
1430     }
1431 
1432     #[test]
1433     fn test_try_transmute() {
1434         // Test that memory is transmuted with `try_transmute` as expected.
1435         let array_of_bools = [false, true, false, true, false, true, false, true];
1436         let array_of_arrays = [[0, 1], [0, 1], [0, 1], [0, 1]];
1437         let x: Result<[[u8; 2]; 4], _> = try_transmute!(array_of_bools);
1438         assert_eq!(x, Ok(array_of_arrays));
1439         let x: Result<[bool; 8], _> = try_transmute!(array_of_arrays);
1440         assert_eq!(x, Ok(array_of_bools));
1441 
1442         // Test that `try_transmute!` works with `!Immutable` types.
1443         let x: Result<usize, _> = try_transmute!(UnsafeCell::new(1usize));
1444         assert_eq!(x.unwrap(), 1);
1445         let x: Result<UnsafeCell<usize>, _> = try_transmute!(1usize);
1446         assert_eq!(x.unwrap().into_inner(), 1);
1447         let x: Result<UnsafeCell<isize>, _> = try_transmute!(UnsafeCell::new(1usize));
1448         assert_eq!(x.unwrap().into_inner(), 1);
1449 
1450         #[derive(FromBytes, IntoBytes, Debug, PartialEq)]
1451         #[repr(transparent)]
1452         struct PanicOnDrop<T>(T);
1453 
1454         impl<T> Drop for PanicOnDrop<T> {
1455             fn drop(&mut self) {
1456                 panic!("PanicOnDrop dropped");
1457             }
1458         }
1459 
1460         // Since `try_transmute!` semantically moves its argument on failure,
1461         // the `PanicOnDrop` is not dropped, and thus this shouldn't panic.
1462         let x: Result<usize, _> = try_transmute!(PanicOnDrop(1usize));
1463         assert_eq!(x, Ok(1));
1464 
1465         // Since `try_transmute!` semantically returns ownership of its argument
1466         // on failure, the `PanicOnDrop` is returned rather than dropped, and
1467         // thus this shouldn't panic.
1468         let y: Result<bool, _> = try_transmute!(PanicOnDrop(2u8));
1469         // We have to use `map_err` instead of comparing against
1470         // `Err(PanicOnDrop(2u8))` because the latter would create and then drop
1471         // its `PanicOnDrop` temporary, which would cause a panic.
1472         assert_eq!(y.as_ref().map_err(|p| &p.src.0), Err::<&bool, _>(&2u8));
1473         mem::forget(y);
1474     }
1475 
1476     #[test]
1477     fn test_try_transmute_ref() {
1478         // Test that memory is transmuted with `try_transmute_ref` as expected.
1479         let array_of_bools = &[false, true, false, true, false, true, false, true];
1480         let array_of_arrays = &[[0, 1], [0, 1], [0, 1], [0, 1]];
1481         let x: Result<&[[u8; 2]; 4], _> = try_transmute_ref!(array_of_bools);
1482         assert_eq!(x, Ok(array_of_arrays));
1483         let x: Result<&[bool; 8], _> = try_transmute_ref!(array_of_arrays);
1484         assert_eq!(x, Ok(array_of_bools));
1485 
1486         // Test that it's legal to transmute a reference while shrinking the
1487         // lifetime.
1488         {
1489             let x: Result<&[[u8; 2]; 4], _> = try_transmute_ref!(array_of_bools);
1490             assert_eq!(x, Ok(array_of_arrays));
1491         }
1492 
1493         // Test that `try_transmute_ref!` supports decreasing alignment.
1494         let u = AU64(0);
1495         let array = [0u8, 0, 0, 0, 0, 0, 0, 0];
1496         let x: Result<&[u8; 8], _> = try_transmute_ref!(&u);
1497         assert_eq!(x, Ok(&array));
1498 
1499         // Test that a mutable reference can be turned into an immutable one.
1500         let mut x = 0u8;
1501         #[allow(clippy::useless_transmute)]
1502         let y: Result<&u8, _> = try_transmute_ref!(&mut x);
1503         assert_eq!(y, Ok(&0));
1504 
1505         // Test that sized types work which don't implement `KnownLayout`.
1506         let array_of_nkl_u8s = Nkl([0u8, 1, 2, 3, 4, 5, 6, 7]);
1507         let array_of_nkl_arrays = Nkl([[0, 1], [2, 3], [4, 5], [6, 7]]);
1508         let x: Result<&Nkl<[[u8; 2]; 4]>, _> = try_transmute_ref!(&array_of_nkl_u8s);
1509         assert_eq!(x, Ok(&array_of_nkl_arrays));
1510 
1511         // Test sized -> unsized transmutation.
1512         let array_of_u8s = [0u8, 1, 2, 3, 4, 5, 6, 7];
1513         let array_of_arrays = [[0, 1], [2, 3], [4, 5], [6, 7]];
1514         let slice_of_arrays = &array_of_arrays[..];
1515         let x: Result<&[[u8; 2]], _> = try_transmute_ref!(&array_of_u8s);
1516         assert_eq!(x, Ok(slice_of_arrays));
1517 
1518         // Test unsized -> unsized transmutation.
1519         let slice_dst_of_u8s =
1520             SliceDst::<U16, [u8; 2]>::ref_from_bytes(&[0, 1, 2, 3, 4, 5][..]).unwrap();
1521         let slice_dst_of_u16s =
1522             SliceDst::<U16, U16>::ref_from_bytes(&[0, 1, 2, 3, 4, 5][..]).unwrap();
1523         let x: Result<&SliceDst<U16, U16>, _> = try_transmute_ref!(slice_dst_of_u8s);
1524         assert_eq!(x, Ok(slice_dst_of_u16s));
1525     }
1526 
1527     #[test]
1528     fn test_try_transmute_mut() {
1529         // Test that memory is transmuted with `try_transmute_mut` as expected.
1530         let array_of_u8s = &mut [0u8, 1, 0, 1, 0, 1, 0, 1];
1531         let array_of_arrays = &mut [[0u8, 1], [0, 1], [0, 1], [0, 1]];
1532         let x: Result<&mut [[u8; 2]; 4], _> = try_transmute_mut!(array_of_u8s);
1533         assert_eq!(x, Ok(array_of_arrays));
1534 
1535         let array_of_bools = &mut [false, true, false, true, false, true, false, true];
1536         let array_of_arrays = &mut [[0u8, 1], [0, 1], [0, 1], [0, 1]];
1537         let x: Result<&mut [bool; 8], _> = try_transmute_mut!(array_of_arrays);
1538         assert_eq!(x, Ok(array_of_bools));
1539 
1540         // Test that it's legal to transmute a reference while shrinking the
1541         // lifetime.
1542         let array_of_bools = &mut [false, true, false, true, false, true, false, true];
1543         let array_of_arrays = &mut [[0u8, 1], [0, 1], [0, 1], [0, 1]];
1544         {
1545             let x: Result<&mut [bool; 8], _> = try_transmute_mut!(array_of_arrays);
1546             assert_eq!(x, Ok(array_of_bools));
1547         }
1548 
1549         // Test that `try_transmute_mut!` supports decreasing alignment.
1550         let u = &mut AU64(0);
1551         let array = &mut [0u8, 0, 0, 0, 0, 0, 0, 0];
1552         let x: Result<&mut [u8; 8], _> = try_transmute_mut!(u);
1553         assert_eq!(x, Ok(array));
1554 
1555         // Test that a mutable reference can be turned into an immutable one.
1556         let mut x = 0u8;
1557         #[allow(clippy::useless_transmute)]
1558         let y: Result<&mut u8, _> = try_transmute_mut!(&mut x);
1559         assert_eq!(y, Ok(&mut 0));
1560 
1561         // Test that sized types work which don't implement `KnownLayout`.
1562         let mut array_of_nkl_u8s = Nkl([0u8, 1, 2, 3, 4, 5, 6, 7]);
1563         let mut array_of_nkl_arrays = Nkl([[0, 1], [2, 3], [4, 5], [6, 7]]);
1564         let x: Result<&mut Nkl<[[u8; 2]; 4]>, _> = try_transmute_mut!(&mut array_of_nkl_u8s);
1565         assert_eq!(x, Ok(&mut array_of_nkl_arrays));
1566 
1567         // Test sized -> unsized transmutation.
1568         let mut array_of_u8s = [0u8, 1, 2, 3, 4, 5, 6, 7];
1569         let mut array_of_arrays = [[0, 1], [2, 3], [4, 5], [6, 7]];
1570         let slice_of_arrays = &mut array_of_arrays[..];
1571         let x: Result<&mut [[u8; 2]], _> = try_transmute_mut!(&mut array_of_u8s);
1572         assert_eq!(x, Ok(slice_of_arrays));
1573 
1574         // Test unsized -> unsized transmutation.
1575         let mut bytes = [0, 1, 2, 3, 4, 5, 6];
1576         let slice_dst_of_u8s = SliceDst::<u8, [u8; 2]>::mut_from_bytes(&mut bytes[..]).unwrap();
1577         let mut bytes = [0, 1, 2, 3, 4, 5, 6];
1578         let slice_dst_of_u16s = SliceDst::<u8, U16>::mut_from_bytes(&mut bytes[..]).unwrap();
1579         let x: Result<&mut SliceDst<u8, U16>, _> = try_transmute_mut!(slice_dst_of_u8s);
1580         assert_eq!(x, Ok(slice_dst_of_u16s));
1581     }
1582 
1583     #[test]
1584     fn test_transmute_mut() {
1585         // Test that memory is transmuted as expected.
1586         let mut array_of_u8s = [0u8, 1, 2, 3, 4, 5, 6, 7];
1587         let mut array_of_arrays = [[0, 1], [2, 3], [4, 5], [6, 7]];
1588         let x: &mut [[u8; 2]; 4] = transmute_mut!(&mut array_of_u8s);
1589         assert_eq!(*x, array_of_arrays);
1590         let x: &mut [u8; 8] = transmute_mut!(&mut array_of_arrays);
1591         assert_eq!(*x, array_of_u8s);
1592 
1593         {
1594             // Test that it's legal to transmute a reference while shrinking the
1595             // lifetime.
1596             let x: &mut [u8; 8] = transmute_mut!(&mut array_of_arrays);
1597             assert_eq!(*x, array_of_u8s);
1598         }
1599 
1600         // Test that `transmute_mut!` supports non-`KnownLayout` types.
1601         let mut array_of_u8s = Nkl([0u8, 1, 2, 3, 4, 5, 6, 7]);
1602         let mut array_of_arrays = Nkl([[0, 1], [2, 3], [4, 5], [6, 7]]);
1603         let x: &mut Nkl<[[u8; 2]; 4]> = transmute_mut!(&mut array_of_u8s);
1604         assert_eq!(*x, array_of_arrays);
1605         let x: &mut Nkl<[u8; 8]> = transmute_mut!(&mut array_of_arrays);
1606         assert_eq!(*x, array_of_u8s);
1607 
1608         // Test that `transmute_mut!` supports decreasing alignment.
1609         let mut u = AU64(0);
1610         let array = [0, 0, 0, 0, 0, 0, 0, 0];
1611         let x: &[u8; 8] = transmute_mut!(&mut u);
1612         assert_eq!(*x, array);
1613 
1614         // Test that a mutable reference can be turned into an immutable one.
1615         let mut x = 0u8;
1616         #[allow(clippy::useless_transmute)]
1617         let y: &u8 = transmute_mut!(&mut x);
1618         assert_eq!(*y, 0);
1619 
1620         // Test that `transmute_mut!` works on slice DSTs in and that memory is
1621         // transmuted as expected.
1622         let mut bytes = [0, 1, 2, 3, 4, 5, 6];
1623         let slice_dst_of_u8s = SliceDst::<u8, [u8; 2]>::mut_from_bytes(&mut bytes[..]).unwrap();
1624         let mut bytes = [0, 1, 2, 3, 4, 5, 6];
1625         let slice_dst_of_u16s = SliceDst::<u8, U16>::mut_from_bytes(&mut bytes[..]).unwrap();
1626         let x: &mut SliceDst<u8, U16> = transmute_mut!(slice_dst_of_u8s);
1627         assert_eq!(x, slice_dst_of_u16s);
1628 
1629         // Test that `transmute_mut!` works on slices that memory is transmuted
1630         // as expected.
1631         let array_of_u16s: &mut [u16] = &mut [0u16, 1, 2];
1632         let array_of_i16s: &mut [i16] = &mut [0i16, 1, 2];
1633         let x: &mut [i16] = transmute_mut!(array_of_u16s);
1634         assert_eq!(x, array_of_i16s);
1635 
1636         // Test that transmuting from a type with larger trailing slice offset
1637         // and larger trailing slice element works.
1638         let mut bytes = [0, 1, 2, 3, 4, 5, 6, 7];
1639         let slice_dst_big = SliceDst::<U32, U16>::mut_from_bytes(&mut bytes[..]).unwrap();
1640         let mut bytes = [0, 1, 2, 3, 4, 5, 6, 7];
1641         let slice_dst_small = SliceDst::<U16, u8>::mut_from_bytes(&mut bytes[..]).unwrap();
1642         let x: &mut SliceDst<U16, u8> = transmute_mut!(slice_dst_big);
1643         assert_eq!(x, slice_dst_small);
1644 
1645         // Test sized -> unsized transmutation.
1646         let mut array_of_u8s = [0u8, 1, 2, 3, 4, 5, 6, 7];
1647         let mut array_of_arrays = [[0, 1], [2, 3], [4, 5], [6, 7]];
1648         let slice_of_arrays = &mut array_of_arrays[..];
1649         let x: &mut [[u8; 2]] = transmute_mut!(&mut array_of_u8s);
1650         assert_eq!(x, slice_of_arrays);
1651     }
1652 
1653     #[test]
1654     fn test_macros_evaluate_args_once() {
1655         let mut ctr = 0;
1656         #[allow(clippy::useless_transmute)]
1657         let _: usize = transmute!({
1658             ctr += 1;
1659             0usize
1660         });
1661         assert_eq!(ctr, 1);
1662 
1663         let mut ctr = 0;
1664         let _: &usize = transmute_ref!({
1665             ctr += 1;
1666             &0usize
1667         });
1668         assert_eq!(ctr, 1);
1669 
1670         let mut ctr: usize = 0;
1671         let _: &mut usize = transmute_mut!({
1672             ctr += 1;
1673             &mut ctr
1674         });
1675         assert_eq!(ctr, 1);
1676 
1677         let mut ctr = 0;
1678         #[allow(clippy::useless_transmute)]
1679         let _: usize = try_transmute!({
1680             ctr += 1;
1681             0usize
1682         })
1683         .unwrap();
1684         assert_eq!(ctr, 1);
1685     }
1686 
1687     #[test]
1688     fn test_include_value() {
1689         const AS_U32: u32 = include_value!("../testdata/include_value/data");
1690         assert_eq!(AS_U32, u32::from_ne_bytes([b'a', b'b', b'c', b'd']));
1691         const AS_I32: i32 = include_value!("../testdata/include_value/data");
1692         assert_eq!(AS_I32, i32::from_ne_bytes([b'a', b'b', b'c', b'd']));
1693     }
1694 
1695     #[test]
1696     #[allow(non_camel_case_types, unreachable_pub, dead_code)]
1697     fn test_cryptocorrosion_derive_traits() {
1698         // Test the set of invocations added in
1699         // https://github.com/cryptocorrosion/cryptocorrosion/pull/85
1700 
1701         fn assert_impls<T: FromBytes + IntoBytes + Immutable>() {}
1702 
1703         cryptocorrosion_derive_traits! {
1704             #[repr(C)]
1705             #[derive(Clone, Copy)]
1706             pub union vec128_storage {
1707                 d: [u32; 4],
1708                 q: [u64; 2],
1709             }
1710         }
1711 
1712         assert_impls::<vec128_storage>();
1713 
1714         cryptocorrosion_derive_traits! {
1715             #[repr(transparent)]
1716             #[derive(Copy, Clone, Debug, PartialEq)]
1717             pub struct u32x4_generic([u32; 4]);
1718         }
1719 
1720         assert_impls::<u32x4_generic>();
1721 
1722         cryptocorrosion_derive_traits! {
1723             #[repr(transparent)]
1724             #[derive(Copy, Clone, Debug, PartialEq)]
1725             pub struct u64x2_generic([u64; 2]);
1726         }
1727 
1728         assert_impls::<u64x2_generic>();
1729 
1730         cryptocorrosion_derive_traits! {
1731             #[repr(transparent)]
1732             #[derive(Copy, Clone, Debug, PartialEq)]
1733             pub struct u128x1_generic([u128; 1]);
1734         }
1735 
1736         assert_impls::<u128x1_generic>();
1737 
1738         cryptocorrosion_derive_traits! {
1739             #[repr(transparent)]
1740             #[derive(Copy, Clone, Default)]
1741             #[allow(non_camel_case_types)]
1742             pub struct x2<W, G>(pub [W; 2], PhantomData<G>);
1743         }
1744 
1745         enum NotZerocopy {}
1746         assert_impls::<x2<(), NotZerocopy>>();
1747 
1748         cryptocorrosion_derive_traits! {
1749             #[repr(transparent)]
1750             #[derive(Copy, Clone, Default)]
1751             #[allow(non_camel_case_types)]
1752             pub struct x4<W>(pub [W; 4]);
1753         }
1754 
1755         assert_impls::<x4<()>>();
1756 
1757         #[cfg(feature = "simd")]
1758         #[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
1759         {
1760             #[cfg(target_arch = "x86")]
1761             use core::arch::x86::{__m128i, __m256i};
1762             #[cfg(target_arch = "x86_64")]
1763             use core::arch::x86_64::{__m128i, __m256i};
1764 
1765             cryptocorrosion_derive_traits! {
1766                 #[repr(C)]
1767                 #[derive(Copy, Clone)]
1768                 pub struct X4(__m128i, __m128i, __m128i, __m128i);
1769             }
1770 
1771             assert_impls::<X4>();
1772 
1773             cryptocorrosion_derive_traits! {
1774                 #[repr(C)]
1775                 /// Generic wrapper for unparameterized storage of any of the
1776                 /// possible impls. Converting into and out of this type should
1777                 /// be essentially free, although it may be more aligned than a
1778                 /// particular impl requires.
1779                 #[allow(non_camel_case_types)]
1780                 #[derive(Copy, Clone)]
1781                 pub union vec128_storage {
1782                     u32x4: [u32; 4],
1783                     u64x2: [u64; 2],
1784                     u128x1: [u128; 1],
1785                     sse2: __m128i,
1786                 }
1787             }
1788 
1789             assert_impls::<vec128_storage>();
1790 
1791             cryptocorrosion_derive_traits! {
1792                 #[repr(transparent)]
1793                 #[allow(non_camel_case_types)]
1794                 #[derive(Copy, Clone)]
1795                 pub struct vec<S3, S4, NI> {
1796                     x: __m128i,
1797                     s3: PhantomData<S3>,
1798                     s4: PhantomData<S4>,
1799                     ni: PhantomData<NI>,
1800                 }
1801             }
1802 
1803             assert_impls::<vec<NotZerocopy, NotZerocopy, NotZerocopy>>();
1804 
1805             cryptocorrosion_derive_traits! {
1806                 #[repr(transparent)]
1807                 #[derive(Copy, Clone)]
1808                 pub struct u32x4x2_avx2<NI> {
1809                     x: __m256i,
1810                     ni: PhantomData<NI>,
1811                 }
1812             }
1813 
1814             assert_impls::<u32x4x2_avx2<NotZerocopy>>();
1815         }
1816 
1817         // Make sure that our derive works for `#[repr(C)]` structs even though
1818         // cryptocorrosion doesn't currently have any.
1819         cryptocorrosion_derive_traits! {
1820             #[repr(C)]
1821             #[derive(Copy, Clone, Debug, PartialEq)]
1822             pub struct ReprC(u8, u8, u16);
1823         }
1824     }
1825 }
1826