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