xref: /linux/rust/zerocopy/src/util/macro_util.rs (revision c37398010a05055e78cf0c75defb90df06c4e999)
1 // Copyright 2022 The Fuchsia Authors
2 //
3 // Licensed under a BSD-style license <LICENSE-BSD>, Apache License, Version 2.0
4 // <LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0>, or the MIT
5 // license <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your option.
6 // This file may not be copied, modified, or distributed except according to
7 // those terms.
8 
9 //! Utilities used by macros and by `zerocopy-derive`.
10 //!
11 //! These are defined here `zerocopy` rather than in code generated by macros or
12 //! by `zerocopy-derive` so that they can be compiled once rather than
13 //! recompiled for every invocation (e.g., if they were defined in generated
14 //! code, then deriving `IntoBytes` and `FromBytes` on three different types
15 //! would result in the code in question being emitted and compiled six
16 //! different times).
17 
18 #![allow(missing_debug_implementations)]
19 
20 // FIXME(#29), FIXME(https://github.com/rust-lang/rust/issues/69835): Remove
21 // this `cfg` when `size_of_val_raw` is stabilized.
22 #[cfg(__ZEROCOPY_INTERNAL_USE_ONLY_NIGHTLY_FEATURES_IN_TESTS)]
23 #[cfg(not(target_pointer_width = "16"))]
24 use core::ptr::{self, NonNull};
25 use core::{marker::PhantomData, mem, num::Wrapping};
26 
27 use crate::{
28     pointer::{
29         cast::CastSized,
30         invariant::{Aligned, Initialized, Valid},
31         BecauseImmutable,
32     },
33     FromBytes, Immutable, IntoBytes, KnownLayout, Ptr, ReadOnly, TryFromBytes, ValidityError,
34 };
35 
36 /// Projects the type of the field at `Index` in `Self` without regard for field
37 /// privacy.
38 ///
39 /// The `Index` parameter is any sort of handle that identifies the field; its
40 /// definition is the obligation of the implementer.
41 ///
42 /// # Safety
43 ///
44 /// Unsafe code may assume that this accurately reflects the definition of
45 /// `Self`.
46 pub unsafe trait Field<Index> {
47     /// The type of the field at `Index`.
48     type Type: ?Sized;
49 }
50 
51 #[cfg_attr(
52     not(no_zerocopy_diagnostic_on_unimplemented_1_78_0),
53     diagnostic::on_unimplemented(
54         message = "`{T}` has {PADDING_BYTES} total byte(s) of padding",
55         label = "types with padding cannot implement `IntoBytes`",
56         note = "consider using `zerocopy::Unalign` to lower the alignment of individual fields",
57         note = "consider adding explicit fields where padding would be",
58         note = "consider using `#[repr(packed)]` to remove padding"
59     )
60 )]
61 pub trait PaddingFree<T: ?Sized, const PADDING_BYTES: usize> {}
62 impl<T: ?Sized> PaddingFree<T, 0> for () {}
63 
64 // FIXME(#1112): In the slice DST case, we should delegate to *both*
65 // `PaddingFree` *and* `DynamicPaddingFree` (and probably rename `PaddingFree`
66 // to `StaticPaddingFree` or something - or introduce a third trait with that
67 // name) so that we can have more clear error messages.
68 
69 #[cfg_attr(
70     not(no_zerocopy_diagnostic_on_unimplemented_1_78_0),
71     diagnostic::on_unimplemented(
72         message = "`{T}` has one or more padding bytes",
73         label = "types with padding cannot implement `IntoBytes`",
74         note = "consider using `zerocopy::Unalign` to lower the alignment of individual fields",
75         note = "consider adding explicit fields where padding would be",
76         note = "consider using `#[repr(packed)]` to remove padding"
77     )
78 )]
79 pub trait DynamicPaddingFree<T: ?Sized, const HAS_PADDING: bool> {}
80 impl<T: ?Sized> DynamicPaddingFree<T, false> for () {}
81 
82 #[cfg(__ZEROCOPY_INTERNAL_USE_ONLY_NIGHTLY_FEATURES_IN_TESTS)]
83 #[cfg(not(target_pointer_width = "16"))]
84 const _64K: usize = 1 << 16;
85 
86 // FIXME(#29), FIXME(https://github.com/rust-lang/rust/issues/69835): Remove
87 // this `cfg` when `size_of_val_raw` is stabilized.
88 #[cfg(__ZEROCOPY_INTERNAL_USE_ONLY_NIGHTLY_FEATURES_IN_TESTS)]
89 #[cfg(not(target_pointer_width = "16"))]
90 #[repr(C, align(65536))]
91 struct Aligned64kAllocation([u8; _64K]);
92 
93 /// A pointer to an aligned allocation of size 2^16.
94 ///
95 /// # Safety
96 ///
97 /// `ALIGNED_64K_ALLOCATION` is guaranteed to point to the entirety of an
98 /// allocation with size and alignment 2^16, and to have valid provenance.
99 // FIXME(#29), FIXME(https://github.com/rust-lang/rust/issues/69835): Remove
100 // this `cfg` when `size_of_val_raw` is stabilized.
101 #[cfg(__ZEROCOPY_INTERNAL_USE_ONLY_NIGHTLY_FEATURES_IN_TESTS)]
102 #[cfg(not(target_pointer_width = "16"))]
103 pub const ALIGNED_64K_ALLOCATION: NonNull<[u8]> = {
104     const REF: &Aligned64kAllocation = &Aligned64kAllocation([0; _64K]);
105     let ptr: *const Aligned64kAllocation = REF;
106     let ptr: *const [u8] = ptr::slice_from_raw_parts(ptr.cast(), _64K);
107     // SAFETY:
108     // - `ptr` is derived from a Rust reference, which is guaranteed to be
109     //   non-null.
110     // - `ptr` is derived from an `&Aligned64kAllocation`, which has size and
111     //   alignment `_64K` as promised. Its length is initialized to `_64K`,
112     //   which means that it refers to the entire allocation.
113     // - `ptr` is derived from a Rust reference, which is guaranteed to have
114     //   valid provenance.
115     //
116     // FIXME(#429): Once `NonNull::new_unchecked` docs document that it
117     // preserves provenance, cite those docs.
118     // FIXME: Replace this `as` with `ptr.cast_mut()` once our MSRV >= 1.65
119     #[allow(clippy::as_conversions)]
120     unsafe {
121         NonNull::new_unchecked(ptr as *mut _)
122     }
123 };
124 
125 /// Computes the offset of the base of the field `$trailing_field_name` within
126 /// the type `$ty`.
127 ///
128 /// `trailing_field_offset!` produces code which is valid in a `const` context.
129 // FIXME(#29), FIXME(https://github.com/rust-lang/rust/issues/69835): Remove
130 // this `cfg` when `size_of_val_raw` is stabilized.
131 #[cfg(__ZEROCOPY_INTERNAL_USE_ONLY_NIGHTLY_FEATURES_IN_TESTS)]
132 #[doc(hidden)] // `#[macro_export]` bypasses this module's `#[doc(hidden)]`.
133 #[macro_export]
134 macro_rules! trailing_field_offset {
135     ($ty:ty, $trailing_field_name:tt) => {{
136         let min_size = {
137             let zero_elems: *const [()] =
138                 $crate::util::macro_util::core_reexport::ptr::slice_from_raw_parts(
139                     $crate::util::macro_util::core_reexport::ptr::NonNull::<()>::dangling()
140                         .as_ptr()
141                         .cast_const(),
142                     0,
143                 );
144             // SAFETY:
145             // - If `$ty` is `Sized`, `size_of_val_raw` is always safe to call.
146             // - Otherwise:
147             //   - If `$ty` is not a slice DST, this pointer conversion will
148             //     fail due to "mismatched vtable kinds", and compilation will
149             //     fail.
150             //   - If `$ty` is a slice DST, we have constructed `zero_elems` to
151             //     have zero trailing slice elements. Per the `size_of_val_raw`
152             //     docs, "For the special case where the dynamic tail length is
153             //     0, this function is safe to call." [1]
154             //
155             // [1] https://doc.rust-lang.org/nightly/std/mem/fn.size_of_val_raw.html
156             unsafe {
157                 #[allow(clippy::as_conversions)]
158                 $crate::util::macro_util::core_reexport::mem::size_of_val_raw(
159                     zero_elems as *const $ty,
160                 )
161             }
162         };
163 
164         assert!(min_size <= _64K);
165 
166         #[allow(clippy::as_conversions)]
167         let ptr = ALIGNED_64K_ALLOCATION.as_ptr() as *const $ty;
168 
169         // SAFETY:
170         // - Thanks to the preceding `assert!`, we know that the value with zero
171         //   elements fits in `_64K` bytes, and thus in the allocation addressed
172         //   by `ALIGNED_64K_ALLOCATION`. The offset of the trailing field is
173         //   guaranteed to be no larger than this size, so this field projection
174         //   is guaranteed to remain in-bounds of its allocation.
175         // - Because the minimum size is no larger than `_64K` bytes, and
176         //   because an object's size must always be a multiple of its alignment
177         //   [1], we know that `$ty`'s alignment is no larger than `_64K`. The
178         //   allocation addressed by `ALIGNED_64K_ALLOCATION` is guaranteed to
179         //   be aligned to `_64K`, so `ptr` is guaranteed to satisfy `$ty`'s
180         //   alignment.
181         // - As required by `addr_of!`, we do not write through `field`.
182         //
183         //   Note that, as of [2], this requirement is technically unnecessary
184         //   for Rust versions >= 1.75.0, but no harm in guaranteeing it anyway
185         //   until we bump our MSRV.
186         //
187         // [1] Per https://doc.rust-lang.org/reference/type-layout.html:
188         //
189         //   The size of a value is always a multiple of its alignment.
190         //
191         // [2] https://github.com/rust-lang/reference/pull/1387
192         let field = unsafe {
193             $crate::util::macro_util::core_reexport::ptr::addr_of!((*ptr).$trailing_field_name)
194         };
195         // SAFETY:
196         // - Both `ptr` and `field` are derived from the same allocated object.
197         // - By the preceding safety comment, `field` is in bounds of that
198         //   allocated object.
199         // - The distance, in bytes, between `ptr` and `field` is required to be
200         //   a multiple of the size of `u8`, which is trivially true because
201         //   `u8`'s size is 1.
202         // - The distance, in bytes, cannot overflow `isize`. This is guaranteed
203         //   because no allocated object can have a size larger than can fit in
204         //   `isize`. [1]
205         // - The distance being in-bounds cannot rely on wrapping around the
206         //   address space. This is guaranteed because the same is guaranteed of
207         //   allocated objects. [1]
208         //
209         // [1] FIXME(#429), FIXME(https://github.com/rust-lang/rust/pull/116675):
210         //     Once these are guaranteed in the Reference, cite it.
211         let offset = unsafe { field.cast::<u8>().offset_from(ptr.cast::<u8>()) };
212         // Guaranteed not to be lossy: `field` comes after `ptr`, so the offset
213         // from `ptr` to `field` is guaranteed to be positive.
214         assert!(offset >= 0);
215         Some(
216             #[allow(clippy::as_conversions)]
217             {
218                 offset as usize
219             },
220         )
221     }};
222 }
223 
224 /// Computes alignment of `$ty: ?Sized`.
225 ///
226 /// `align_of!` produces code which is valid in a `const` context.
227 // FIXME(#29), FIXME(https://github.com/rust-lang/rust/issues/69835): Remove
228 // this `cfg` when `size_of_val_raw` is stabilized.
229 #[cfg(__ZEROCOPY_INTERNAL_USE_ONLY_NIGHTLY_FEATURES_IN_TESTS)]
230 #[doc(hidden)] // `#[macro_export]` bypasses this module's `#[doc(hidden)]`.
231 #[macro_export]
232 macro_rules! align_of {
233     ($ty:ty) => {{
234         // SAFETY: `OffsetOfTrailingIsAlignment` is `repr(C)`, and its layout is
235         // guaranteed [1] to begin with the single-byte layout for `_byte`,
236         // followed by the padding needed to align `_trailing`, then the layout
237         // for `_trailing`, and finally any trailing padding bytes needed to
238         // correctly-align the entire struct.
239         //
240         // This macro computes the alignment of `$ty` by counting the number of
241         // bytes preceding `_trailing`. For instance, if the alignment of `$ty`
242         // is `1`, then no padding is required align `_trailing` and it will be
243         // located immediately after `_byte` at offset 1. If the alignment of
244         // `$ty` is 2, then a single padding byte is required before
245         // `_trailing`, and `_trailing` will be located at offset 2.
246 
247         // This correspondence between offset and alignment holds for all valid
248         // Rust alignments, and we confirm this exhaustively (or, at least up to
249         // the maximum alignment supported by `trailing_field_offset!`) in
250         // `test_align_of_dst`.
251         //
252         // [1]: https://doc.rust-lang.org/nomicon/other-reprs.html#reprc
253 
254         #[repr(C)]
255         struct OffsetOfTrailingIsAlignment {
256             _byte: u8,
257             _trailing: $ty,
258         }
259 
260         trailing_field_offset!(OffsetOfTrailingIsAlignment, _trailing)
261     }};
262 }
263 
264 mod size_to_tag {
265     pub trait SizeToTag<const SIZE: usize> {
266         type Tag;
267     }
268 
269     impl SizeToTag<1> for () {
270         type Tag = u8;
271     }
272     impl SizeToTag<2> for () {
273         type Tag = u16;
274     }
275     impl SizeToTag<4> for () {
276         type Tag = u32;
277     }
278     impl SizeToTag<8> for () {
279         type Tag = u64;
280     }
281     impl SizeToTag<16> for () {
282         type Tag = u128;
283     }
284 }
285 
286 /// An alias for the unsigned integer of the given size in bytes.
287 #[doc(hidden)]
288 pub type SizeToTag<const SIZE: usize> = <() as size_to_tag::SizeToTag<SIZE>>::Tag;
289 
290 // We put `Sized` in its own module so it can have the same name as the standard
291 // library `Sized` without shadowing it in the parent module.
292 #[cfg(not(no_zerocopy_diagnostic_on_unimplemented_1_78_0))]
293 mod __size_of {
294     #[diagnostic::on_unimplemented(
295         message = "`{Self}` is unsized",
296         label = "`IntoBytes` needs all field types to be `Sized` in order to determine whether there is padding",
297         note = "consider using `#[repr(packed)]` to remove padding",
298         note = "`IntoBytes` does not require the fields of `#[repr(packed)]` types to be `Sized`"
299     )]
300     pub trait Sized: core::marker::Sized {}
301     impl<T: core::marker::Sized> Sized for T {}
302 
303     #[inline(always)]
304     #[must_use]
305     #[allow(clippy::needless_maybe_sized)]
306     pub const fn size_of<T: Sized + ?core::marker::Sized>() -> usize {
307         core::mem::size_of::<T>()
308     }
309 }
310 
311 #[cfg(no_zerocopy_diagnostic_on_unimplemented_1_78_0)]
312 pub use core::mem::size_of;
313 
314 #[cfg(not(no_zerocopy_diagnostic_on_unimplemented_1_78_0))]
315 pub use __size_of::size_of;
316 
317 /// How many padding bytes does the struct type `$t` have?
318 ///
319 /// `$ts` is the list of the type of every field in `$t`. `$t` must be a struct
320 /// type, or else `struct_padding!`'s result may be meaningless.
321 ///
322 /// Note that `struct_padding!`'s results are independent of `repcr` since they
323 /// only consider the size of the type and the sizes of the fields. Whatever the
324 /// repr, the size of the type already takes into account any padding that the
325 /// compiler has decided to add. Structs with well-defined representations (such
326 /// as `repr(C)`) can use this macro to check for padding. Note that while this
327 /// may yield some consistent value for some `repr(Rust)` structs, it is not
328 /// guaranteed across platforms or compilations.
329 #[doc(hidden)] // `#[macro_export]` bypasses this module's `#[doc(hidden)]`.
330 #[macro_export]
331 macro_rules! struct_padding {
332     ($t:ty, $_align:expr, $_packed:expr, [$($ts:ty),*]) => {{
333         // The `align` and `packed` directives can be ignored here. Regardless
334         // of if and how they are set, comparing the size of `$t` to the sum of
335         // its field sizes is a reliable indicator of the presence of padding.
336         $crate::util::macro_util::size_of::<$t>() - (0 $(+ $crate::util::macro_util::size_of::<$ts>())*)
337     }};
338 }
339 
340 /// Does the `repr(C)` struct type `$t` have padding?
341 ///
342 /// `$ts` is the list of the type of every field in `$t`. `$t` must be a
343 /// `repr(C)` struct type, or else `struct_has_padding!`'s result may be
344 /// meaningless.
345 #[doc(hidden)] // `#[macro_export]` bypasses this module's `#[doc(hidden)]`.
346 #[macro_export]
347 macro_rules! repr_c_struct_has_padding {
348     ($t:ty, $align:expr, $packed:expr, [$($ts:tt),*]) => {{
349         let layout = $crate::DstLayout::for_repr_c_struct(
350             $align,
351             $packed,
352             &[$($crate::repr_c_struct_has_padding!(@field $ts),)*]
353         );
354         layout.requires_static_padding() || layout.requires_dynamic_padding()
355     }};
356     (@field ([$t:ty])) => {
357         <[$t] as $crate::KnownLayout>::LAYOUT
358     };
359     (@field ($t:ty)) => {
360         $crate::DstLayout::for_unpadded_type::<$t>()
361     };
362     (@field [$t:ty]) => {
363         <[$t] as $crate::KnownLayout>::LAYOUT
364     };
365     (@field $t:ty) => {
366         $crate::DstLayout::for_unpadded_type::<$t>()
367     };
368 }
369 
370 /// Does the union type `$t` have padding?
371 ///
372 /// `$ts` is the list of the type of every field in `$t`. `$t` must be a union
373 /// type, or else `union_padding!`'s result may be meaningless.
374 ///
375 /// Note that `union_padding!`'s results are independent of `repr` since they
376 /// only consider the size of the type and the sizes of the fields. Whatever the
377 /// repr, the size of the type already takes into account any padding that the
378 /// compiler has decided to add. Unions with well-defined representations (such
379 /// as `repr(C)`) can use this macro to check for padding. Note that while this
380 /// may yield some consistent value for some `repr(Rust)` unions, it is not
381 /// guaranteed across platforms or compilations.
382 #[doc(hidden)] // `#[macro_export]` bypasses this module's `#[doc(hidden)]`.
383 #[macro_export]
384 macro_rules! union_padding {
385     ($t:ty, $_align:expr, $_packed:expr, [$($ts:ty),*]) => {{
386         // The `align` and `packed` directives can be ignored here. Regardless
387         // of if and how they are set, comparing the size of `$t` to each of its
388         // field sizes is a reliable indicator of the presence of padding.
389         let mut max = 0;
390         $({
391             let padding = $crate::util::macro_util::size_of::<$t>() - $crate::util::macro_util::size_of::<$ts>();
392             if padding > max {
393                 max = padding;
394             }
395         })*
396         max
397     }};
398 }
399 
400 /// How many padding bytes does the enum type `$t` have?
401 ///
402 /// `$disc` is the type of the enum tag, and `$ts` is a list of fields in each
403 /// square-bracket-delimited variant. `$t` must be an enum, or else
404 /// `enum_padding!`'s result may be meaningless. An enum has padding if any of
405 /// its variant structs [1][2] contain padding, and so all of the variants of an
406 /// enum must be "full" in order for the enum to not have padding.
407 ///
408 /// The results of `enum_padding!` require that the enum is not `repr(Rust)`, as
409 /// `repr(Rust)` enums may niche the enum's tag and reduce the total number of
410 /// bytes required to represent the enum as a result. As long as the enum is
411 /// `repr(C)`, `repr(int)`, or `repr(C, int)`, this will consistently return
412 /// whether the enum contains any padding bytes.
413 ///
414 /// [1]: https://doc.rust-lang.org/1.81.0/reference/type-layout.html#reprc-enums-with-fields
415 /// [2]: https://doc.rust-lang.org/1.81.0/reference/type-layout.html#primitive-representation-of-enums-with-fields
416 #[doc(hidden)] // `#[macro_export]` bypasses this module's `#[doc(hidden)]`.
417 #[macro_export]
418 macro_rules! enum_padding {
419     ($t:ty, $_align:expr, $packed:expr, $disc:ty, $([$($ts:ty),*]),*) => {{
420         // The `align` and `packed` directives are irrelevant. `$align` can be
421         // ignored because regardless of if and how it is set, comparing the
422         // size of `$t` to each of its field sizes is a reliable indicator of
423         // the presence of padding. `$packed` is irrelevant because it is
424         // forbidden on enums.
425         #[allow(clippy::as_conversions)]
426         const _: [(); 1] = [(); $packed.is_none() as usize];
427         let mut max = 0;
428         $({
429             let padding = $crate::util::macro_util::size_of::<$t>()
430                 - (
431                     $crate::util::macro_util::size_of::<$disc>()
432                     $(+ $crate::util::macro_util::size_of::<$ts>())*
433                 );
434             if padding > max {
435                 max = padding;
436             }
437         })*
438         max
439     }};
440 }
441 
442 /// Unwraps an infallible `Result`.
443 #[doc(hidden)]
444 #[macro_export]
445 macro_rules! into_inner {
446     ($e:expr) => {
447         match $e {
448             $crate::util::macro_util::core_reexport::result::Result::Ok(e) => e,
449             $crate::util::macro_util::core_reexport::result::Result::Err(i) => match i {},
450         }
451     };
452 }
453 
454 /// Translates an identifier or tuple index into a numeric identifier.
455 #[doc(hidden)] // `#[macro_export]` bypasses this module's `#[doc(hidden)]`.
456 #[macro_export]
457 macro_rules! ident_id {
458     ($field:ident) => {
459         $crate::util::macro_util::hash_name(stringify!($field))
460     };
461     ($field:literal) => {
462         $field
463     };
464 }
465 
466 /// Computes the hash of a string.
467 ///
468 /// NOTE(#2749) on hash collisions: This function's output only needs to be
469 /// deterministic within a particular compilation. Thus, if a user ever reports
470 /// a hash collision (very unlikely given the <= 16-byte special case), we can
471 /// strengthen the hash function at that point and publish a new version. Since
472 /// this is computed at compile time on small strings, we can easily use more
473 /// expensive and higher-quality hash functions if need be.
474 #[inline(always)]
475 #[must_use]
476 #[allow(clippy::as_conversions, clippy::indexing_slicing, clippy::arithmetic_side_effects)]
477 pub const fn hash_name(name: &str) -> i128 {
478     let name = name.as_bytes();
479 
480     // We guarantee freedom from hash collisions between any two strings of
481     // length 16 or less by having the hashes of such strings be equal to
482     // their value. There is still a possibility that such strings will have
483     // the same value as the hash of a string of length > 16.
484     if name.len() <= size_of::<u128>() {
485         let mut bytes = [0u8; 16];
486 
487         let mut i = 0;
488         while i < name.len() {
489             bytes[i] = name[i];
490             i += 1;
491         }
492 
493         return i128::from_ne_bytes(bytes);
494     };
495 
496     // An implementation of FxHasher, although returning a u128. Probably
497     // not as strong as it could be, but probably more collision resistant
498     // than normal 64-bit FxHasher.
499     let mut hash = 0u128;
500     let mut i = 0;
501     while i < name.len() {
502         // This is just FxHasher's `0x517cc1b727220a95` constant
503         // concatenated back-to-back.
504         const K: u128 = 0x517cc1b727220a95517cc1b727220a95;
505         hash = (hash.rotate_left(5) ^ (name[i] as u128)).wrapping_mul(K);
506         i += 1;
507     }
508     i128::from_ne_bytes(hash.to_ne_bytes())
509 }
510 
511 /// Attempts to transmute `Src` into `Dst`.
512 ///
513 /// A helper for `try_transmute!`.
514 ///
515 /// # Panics
516 ///
517 /// `try_transmute` may either produce a post-monomorphization error or a panic
518 /// if `Dst` is bigger than `Src`. Otherwise, `try_transmute` panics under the
519 /// same circumstances as [`is_bit_valid`].
520 ///
521 /// [`is_bit_valid`]: TryFromBytes::is_bit_valid
522 #[inline(always)]
523 pub fn try_transmute<Src, Dst>(src: Src) -> Result<Dst, ValidityError<Src, Dst>>
524 where
525     Src: IntoBytes,
526     Dst: TryFromBytes,
527 {
528     static_assert!(Src, Dst => mem::size_of::<Dst>() == mem::size_of::<Src>());
529 
530     let mu_src = mem::MaybeUninit::new(src);
531     // SAFETY: `MaybeUninit` has no validity requirements.
532     let mu_dst: mem::MaybeUninit<ReadOnly<Dst>> =
533         unsafe { crate::util::transmute_unchecked(mu_src) };
534 
535     let ptr = Ptr::from_ref(&mu_dst);
536 
537     // SAFETY: Since `Src: IntoBytes`, and since `size_of::<Src>() ==
538     // size_of::<Dst>()` by the preceding assertion, all of `mu_dst`'s bytes are
539     // initialized. `MaybeUninit` has no validity requirements, so even if
540     // `ptr` is used to mutate its referent (which it actually can't be - it's
541     // a shared `ReadOnly` pointer), that won't violate its referent's validity.
542     let ptr = unsafe { ptr.assume_validity::<Initialized>() };
543     if Dst::is_bit_valid(ptr.cast::<_, CastSized, _>()) {
544         // SAFETY: Since `Dst::is_bit_valid`, we know that `ptr`'s referent is
545         // bit-valid for `Dst`. `ptr` points to `mu_dst`, and no intervening
546         // operations have mutated it, so it is a bit-valid `Dst`.
547         Ok(ReadOnly::into_inner(unsafe { mu_dst.assume_init() }))
548     } else {
549         // SAFETY: `MaybeUninit` has no validity requirements.
550         let mu_src: mem::MaybeUninit<Src> = unsafe { crate::util::transmute_unchecked(mu_dst) };
551         // SAFETY: `mu_dst`/`mu_src` was constructed from `src` and never
552         // modified, so it is still bit-valid.
553         Err(ValidityError::new(unsafe { mu_src.assume_init() }))
554     }
555 }
556 
557 /// See `try_transmute_ref!` documentation.
558 pub trait TryTransmuteRefDst<'a> {
559     type Dst: ?Sized;
560 
561     /// See `try_transmute_ref!` documentation.
562     fn try_transmute_ref(self) -> Result<&'a Self::Dst, ValidityError<&'a Self::Src, Self::Dst>>
563     where
564         Self: TryTransmuteRefSrc<'a>,
565         Self::Src: IntoBytes + Immutable + KnownLayout,
566         Self::Dst: TryFromBytes + Immutable + KnownLayout;
567 }
568 
569 pub trait TryTransmuteRefSrc<'a> {
570     type Src: ?Sized;
571 }
572 
573 impl<'a, Src, Dst> TryTransmuteRefSrc<'a> for Wrap<&'a Src, &'a Dst>
574 where
575     Src: ?Sized,
576     Dst: ?Sized,
577 {
578     type Src = Src;
579 }
580 
581 impl<'a, Src, Dst> TryTransmuteRefDst<'a> for Wrap<&'a Src, &'a Dst>
582 where
583     Src: IntoBytes + Immutable + KnownLayout + ?Sized,
584     Dst: TryFromBytes + Immutable + KnownLayout + ?Sized,
585 {
586     type Dst = Dst;
587 
588     #[inline(always)]
589     fn try_transmute_ref(
590         self,
591     ) -> Result<
592         &'a Dst,
593         ValidityError<&'a <Wrap<&'a Src, &'a Dst> as TryTransmuteRefSrc<'a>>::Src, Dst>,
594     > {
595         let ptr = Ptr::from_ref(self.0);
596         #[rustfmt::skip]
597         let res = ptr.try_with(#[inline(always)] |ptr| {
598             let ptr = ptr.recall_validity::<Initialized, _>();
599             let ptr = ptr.cast::<_, crate::layout::CastFrom<Dst>, _>();
600             ptr.try_into_valid()
601         });
602         match res {
603             Ok(ptr) => {
604                 static_assert!(Src: ?Sized + KnownLayout, Dst: ?Sized + KnownLayout => {
605                     Src::LAYOUT.align.get() >= Dst::LAYOUT.align.get()
606                 }, "cannot transmute reference when destination type has higher alignment than source type");
607                 // SAFETY: We have checked that `Dst` does not have a stricter
608                 // alignment requirement than `Src`.
609                 let ptr = unsafe { ptr.assume_alignment::<Aligned>() };
610                 Ok(ptr.as_ref())
611             }
612             Err(err) => Err(err.map_src(Ptr::as_ref)),
613         }
614     }
615 }
616 
617 pub trait TryTransmuteMutDst<'a> {
618     type Dst: ?Sized;
619 
620     /// See `try_transmute_mut!` documentation.
621     fn try_transmute_mut(
622         self,
623     ) -> Result<&'a mut Self::Dst, ValidityError<&'a mut Self::Src, Self::Dst>>
624     where
625         Self: TryTransmuteMutSrc<'a>,
626         Self::Src: IntoBytes,
627         Self::Dst: TryFromBytes;
628 }
629 
630 pub trait TryTransmuteMutSrc<'a> {
631     type Src: ?Sized;
632 }
633 
634 impl<'a, Src, Dst> TryTransmuteMutSrc<'a> for Wrap<&'a mut Src, &'a mut Dst>
635 where
636     Src: ?Sized,
637     Dst: ?Sized,
638 {
639     type Src = Src;
640 }
641 
642 impl<'a, Src, Dst> TryTransmuteMutDst<'a> for Wrap<&'a mut Src, &'a mut Dst>
643 where
644     Src: FromBytes + IntoBytes + KnownLayout + ?Sized,
645     Dst: TryFromBytes + IntoBytes + KnownLayout + ?Sized,
646 {
647     type Dst = Dst;
648 
649     #[inline(always)]
650     fn try_transmute_mut(
651         self,
652     ) -> Result<
653         &'a mut Dst,
654         ValidityError<&'a mut <Wrap<&'a mut Src, &'a mut Dst> as TryTransmuteMutSrc<'a>>::Src, Dst>,
655     > {
656         let ptr = Ptr::from_mut(self.0);
657         // SAFETY: The provided closure returns the only copy of `ptr`.
658         #[rustfmt::skip]
659         let res = unsafe {
660             ptr.try_with_unchecked(#[inline(always)] |ptr| {
661                 let ptr = ptr.recall_validity::<Initialized, (_, (_, _))>();
662                 let ptr = ptr.cast::<_, crate::layout::CastFrom<Dst>, _>();
663                 ptr.try_into_valid()
664             })
665         };
666         match res {
667             Ok(ptr) => {
668                 static_assert!(Src: ?Sized + KnownLayout, Dst: ?Sized + KnownLayout => {
669                     Src::LAYOUT.align.get() >= Dst::LAYOUT.align.get()
670                 }, "cannot transmute reference when destination type has higher alignment than source type");
671                 // SAFETY: We have checked that `Dst` does not have a stricter
672                 // alignment requirement than `Src`.
673                 let ptr = unsafe { ptr.assume_alignment::<Aligned>() };
674                 Ok(ptr.as_mut())
675             }
676             Err(err) => Err(err.map_src(Ptr::as_mut)),
677         }
678     }
679 }
680 
681 // Used in `transmute_ref!` and friends.
682 //
683 // This permits us to use the autoref specialization trick to dispatch to
684 // associated functions for `transmute_ref` and `transmute_mut` when both `Src`
685 // and `Dst` are `Sized`, and to trait methods otherwise. The associated
686 // functions, unlike the trait methods, do not require a `KnownLayout` bound.
687 // This permits us to add support for transmuting references to unsized types
688 // without breaking backwards-compatibility (on v0.8.x) with the old
689 // implementation, which did not require a `KnownLayout` bound to transmute
690 // sized types.
691 #[derive(Copy, Clone)]
692 pub struct Wrap<Src, Dst>(pub Src, pub PhantomData<Dst>);
693 
694 impl<Src, Dst> Wrap<Src, Dst> {
695     #[inline(always)]
696     pub const fn new(src: Src) -> Self {
697         Wrap(src, PhantomData)
698     }
699 }
700 
701 impl<'a, Src, Dst> Wrap<&'a Src, &'a Dst>
702 where
703     Src: ?Sized,
704     Dst: ?Sized,
705 {
706     #[allow(clippy::must_use_candidate, clippy::missing_inline_in_public_items, clippy::empty_loop)]
707     pub const fn transmute_ref_inference_helper(self) -> &'a Dst {
708         loop {}
709     }
710 }
711 
712 impl<'a, Src, Dst> Wrap<&'a Src, &'a Dst> {
713     /// # Safety
714     /// The caller must guarantee that:
715     /// - `Src: IntoBytes + Immutable`
716     /// - `Dst: FromBytes + Immutable`
717     ///
718     /// # PME
719     ///
720     /// Instantiating this method PMEs unless both:
721     /// - `mem::size_of::<Dst>() == mem::size_of::<Src>()`
722     /// - `mem::align_of::<Dst>() <= mem::align_of::<Src>()`
723     #[inline(always)]
724     #[must_use]
725     pub const unsafe fn transmute_ref(self) -> &'a Dst {
726         static_assert!(Src, Dst => mem::size_of::<Dst>() == mem::size_of::<Src>());
727         static_assert!(Src, Dst => mem::align_of::<Dst>() <= mem::align_of::<Src>());
728 
729         let src: *const Src = self.0;
730         let dst = src.cast::<Dst>();
731         // SAFETY:
732         // - We know that it is sound to view the target type of the input
733         //   reference (`Src`) as the target type of the output reference
734         //   (`Dst`) because the caller has guaranteed that `Src: IntoBytes`,
735         //   `Dst: FromBytes`, and `size_of::<Src>() == size_of::<Dst>()`.
736         // - We know that there are no `UnsafeCell`s, and thus we don't have to
737         //   worry about `UnsafeCell` overlap, because `Src: Immutable` and
738         //   `Dst: Immutable`.
739         // - The caller has guaranteed that alignment is not increased.
740         // - We know that the returned lifetime will not outlive the input
741         //   lifetime thanks to the lifetime bounds on this function.
742         //
743         // FIXME(#67): Once our MSRV is 1.58, replace this `transmute` with
744         // `&*dst`.
745         #[allow(clippy::transmute_ptr_to_ref)]
746         unsafe {
747             mem::transmute(dst)
748         }
749     }
750 
751     #[inline(always)]
752     pub fn try_transmute_ref(self) -> Result<&'a Dst, ValidityError<&'a Src, Dst>>
753     where
754         Src: IntoBytes + Immutable,
755         Dst: TryFromBytes + Immutable,
756     {
757         static_assert!(Src => mem::align_of::<Src>() == mem::align_of::<Wrapping<Src>>());
758         static_assert!(Dst => mem::align_of::<Dst>() == mem::align_of::<Wrapping<Dst>>());
759 
760         // SAFETY: By the preceding assert, `Src` and `Wrapping<Src>` have the
761         // same alignment.
762         let src: &Wrapping<Src> =
763             unsafe { crate::util::transmute_ref::<_, _, BecauseImmutable>(self.0) };
764         let src = Wrap::new(src);
765         <Wrap<&'a Wrapping<Src>, &'a Wrapping<Dst>> as TryTransmuteRefDst<'a>>::try_transmute_ref(
766             src,
767         )
768         .map(
769             // SAFETY: By the preceding assert, `Dst` and `Wrapping<Dst>` have
770             // the same alignment.
771             #[inline(always)]
772             |dst| unsafe { crate::util::transmute_ref::<_, _, BecauseImmutable>(dst) },
773         )
774         .map_err(
775             #[inline(always)]
776             |err| {
777                 // SAFETY: By the preceding assert, `Src` and `Wrapping<Src>` have the
778                 // same alignment.
779                 ValidityError::new(unsafe {
780                     crate::util::transmute_ref::<_, _, BecauseImmutable>(err.into_src())
781                 })
782             },
783         )
784     }
785 }
786 
787 impl<'a, Src, Dst> Wrap<&'a mut Src, &'a mut Dst>
788 where
789     Src: ?Sized,
790     Dst: ?Sized,
791 {
792     #[allow(clippy::must_use_candidate, clippy::missing_inline_in_public_items, clippy::empty_loop)]
793     pub fn transmute_mut_inference_helper(self) -> &'a mut Dst {
794         loop {}
795     }
796 }
797 
798 impl<'a, Src, Dst> Wrap<&'a mut Src, &'a mut Dst> {
799     /// Transmutes a mutable reference of one type to a mutable reference of
800     /// another type.
801     ///
802     /// # PME
803     ///
804     /// Instantiating this method PMEs unless both:
805     /// - `mem::size_of::<Dst>() == mem::size_of::<Src>()`
806     /// - `mem::align_of::<Dst>() <= mem::align_of::<Src>()`
807     #[inline(always)]
808     #[must_use]
809     pub fn transmute_mut(self) -> &'a mut Dst
810     where
811         Src: FromBytes + IntoBytes,
812         Dst: FromBytes + IntoBytes,
813     {
814         static_assert!(Src, Dst => mem::size_of::<Dst>() == mem::size_of::<Src>());
815         static_assert!(Src, Dst => mem::align_of::<Dst>() <= mem::align_of::<Src>());
816 
817         let src: *mut Src = self.0;
818         let dst = src.cast::<Dst>();
819         // SAFETY:
820         // - We know that it is sound to view the target type of the input
821         //   reference (`Src`) as the target type of the output reference
822         //   (`Dst`) and vice-versa because `Src: FromBytes + IntoBytes`, `Dst:
823         //   FromBytes + IntoBytes`, and (as asserted above) `size_of::<Src>()
824         //   == size_of::<Dst>()`.
825         // - We asserted above that alignment will not increase.
826         // - We know that the returned lifetime will not outlive the input
827         //   lifetime thanks to the lifetime bounds on this function.
828         unsafe { &mut *dst }
829     }
830 
831     #[inline(always)]
832     pub fn try_transmute_mut(self) -> Result<&'a mut Dst, ValidityError<&'a mut Src, Dst>>
833     where
834         Src: FromBytes + IntoBytes,
835         Dst: TryFromBytes + IntoBytes,
836     {
837         static_assert!(Src => mem::align_of::<Src>() == mem::align_of::<Wrapping<Src>>());
838         static_assert!(Dst => mem::align_of::<Dst>() == mem::align_of::<Wrapping<Dst>>());
839 
840         // SAFETY: By the preceding assert, `Src` and `Wrapping<Src>` have the
841         // same alignment.
842         let src: &mut Wrapping<Src> =
843             unsafe { crate::util::transmute_mut::<_, _, (_, (_, _))>(self.0) };
844         let src = Wrap::new(src);
845         <Wrap<&'a mut Wrapping<Src>, &'a mut Wrapping<Dst>> as TryTransmuteMutDst<'a>>
846             ::try_transmute_mut(src)
847             // SAFETY: By the preceding assert, `Dst` and `Wrapping<Dst>` have the
848             // same alignment.
849             .map(|dst| unsafe { crate::util::transmute_mut::<_, _, (_, (_, _))>(dst) })
850             .map_err(|err| {
851                 // SAFETY: By the preceding assert, `Src` and `Wrapping<Src>` have the
852                 // same alignment.
853                 ValidityError::new(unsafe {
854                     crate::util::transmute_mut::<_, _, (_, (_, _))>(err.into_src())
855                 })
856             })
857     }
858 }
859 
860 pub trait TransmuteRefDst<'a> {
861     type Dst: ?Sized;
862 
863     #[must_use]
864     fn transmute_ref(self) -> &'a Self::Dst;
865 }
866 
867 impl<'a, Src: ?Sized, Dst: ?Sized> TransmuteRefDst<'a> for Wrap<&'a Src, &'a Dst>
868 where
869     Src: KnownLayout + IntoBytes + Immutable,
870     Dst: KnownLayout<PointerMetadata = usize> + FromBytes + Immutable,
871 {
872     type Dst = Dst;
873 
874     #[inline(always)]
875     fn transmute_ref(self) -> &'a Dst {
876         let ptr = Ptr::from_ref(self.0)
877             .recall_validity::<Initialized, _>()
878             .transmute_with::<Dst, Initialized, crate::layout::CastFrom<Dst>, (crate::pointer::BecauseMutationCompatible, _)>()
879             .recall_validity::<Valid, _>();
880 
881         static_assert!(Src: ?Sized + KnownLayout, Dst: ?Sized + KnownLayout => {
882             Src::LAYOUT.align.get() >= Dst::LAYOUT.align.get()
883         }, "cannot transmute reference when destination type has higher alignment than source type");
884 
885         // SAFETY: The preceding `static_assert!` ensures that
886         // `Src::LAYOUT.align >= Dst::LAYOUT.align`. Since `self` is
887         // validly-aligned for `Src`, it is also validly-aligned for `Dst`.
888         let ptr = unsafe { ptr.assume_alignment() };
889 
890         ptr.as_ref()
891     }
892 }
893 
894 pub trait TransmuteMutDst<'a> {
895     type Dst: ?Sized;
896     #[must_use]
897     fn transmute_mut(self) -> &'a mut Self::Dst;
898 }
899 
900 impl<'a, Src: ?Sized, Dst: ?Sized> TransmuteMutDst<'a> for Wrap<&'a mut Src, &'a mut Dst>
901 where
902     Src: KnownLayout + FromBytes + IntoBytes,
903     Dst: KnownLayout<PointerMetadata = usize> + FromBytes + IntoBytes,
904 {
905     type Dst = Dst;
906 
907     #[inline(always)]
908     fn transmute_mut(self) -> &'a mut Dst {
909         let ptr = Ptr::from_mut(self.0)
910             .recall_validity::<Initialized, (_, (_, _))>()
911             .transmute_with::<Dst, Initialized, crate::layout::CastFrom<Dst>, _>()
912             .recall_validity::<Valid, (_, (_, _))>();
913 
914         static_assert!(Src: ?Sized + KnownLayout, Dst: ?Sized + KnownLayout => {
915             Src::LAYOUT.align.get() >= Dst::LAYOUT.align.get()
916         }, "cannot transmute reference when destination type has higher alignment than source type");
917 
918         // SAFETY: The preceding `static_assert!` ensures that
919         // `Src::LAYOUT.align >= Dst::LAYOUT.align`. Since `self` is
920         // validly-aligned for `Src`, it is also validly-aligned for `Dst`.
921         let ptr = unsafe { ptr.assume_alignment() };
922 
923         ptr.as_mut()
924     }
925 }
926 
927 /// A function which emits a warning if its return value is not used.
928 #[must_use]
929 #[inline(always)]
930 pub const fn must_use<T>(t: T) -> T {
931     t
932 }
933 
934 // NOTE: We can't change this to a `pub use core as core_reexport` until [1] is
935 // fixed or we update to a semver-breaking version (as of this writing, 0.8.0)
936 // on the `main` branch.
937 //
938 // [1] https://github.com/obi1kenobi/cargo-semver-checks/issues/573
939 pub mod core_reexport {
940     pub use core::*;
941 
942     pub mod mem {
943         pub use core::mem::*;
944     }
945 }
946 
947 #[cfg(test)]
948 mod tests {
949     use core::num::NonZeroUsize;
950 
951     use crate::util::testutil::*;
952 
953     #[cfg(__ZEROCOPY_INTERNAL_USE_ONLY_NIGHTLY_FEATURES_IN_TESTS)]
954     mod nightly {
955         use super::super::*;
956         use crate::util::testutil::*;
957 
958         // FIXME(#29), FIXME(https://github.com/rust-lang/rust/issues/69835):
959         // Remove this `cfg` when `size_of_val_raw` is stabilized.
960         #[allow(clippy::decimal_literal_representation)]
961         #[test]
962         fn test_trailing_field_offset() {
963             assert_eq!(mem::align_of::<Aligned64kAllocation>(), _64K);
964 
965             macro_rules! test {
966                 (#[$cfg:meta] ($($ts:ty),* ; $trailing_field_ty:ty) => $expect:expr) => {{
967                     #[$cfg]
968                     struct Test($(#[allow(dead_code)] $ts,)* #[allow(dead_code)] $trailing_field_ty);
969                     assert_eq!(test!(@offset $($ts),* ; $trailing_field_ty), $expect);
970                 }};
971                 (#[$cfg:meta] $(#[$cfgs:meta])* ($($ts:ty),* ; $trailing_field_ty:ty) => $expect:expr) => {
972                     test!(#[$cfg] ($($ts),* ; $trailing_field_ty) => $expect);
973                     test!($(#[$cfgs])* ($($ts),* ; $trailing_field_ty) => $expect);
974                 };
975                 (@offset ; $_trailing:ty) => { trailing_field_offset!(Test, 0) };
976                 (@offset $_t:ty ; $_trailing:ty) => { trailing_field_offset!(Test, 1) };
977             }
978 
979             test!(#[repr(C)] #[repr(transparent)] #[repr(packed)](; u8) => Some(0));
980             test!(#[repr(C)] #[repr(transparent)] #[repr(packed)](; [u8]) => Some(0));
981             test!(#[repr(C)] #[repr(C, packed)] (u8; u8) => Some(1));
982             test!(#[repr(C)] (; AU64) => Some(0));
983             test!(#[repr(C)] (; [AU64]) => Some(0));
984             test!(#[repr(C)] (u8; AU64) => Some(8));
985             test!(#[repr(C)] (u8; [AU64]) => Some(8));
986 
987             #[derive(
988                 Immutable, FromBytes, Eq, PartialEq, Ord, PartialOrd, Default, Debug, Copy, Clone,
989             )]
990             #[repr(C)]
991             pub(crate) struct Nested<T, U: ?Sized> {
992                 _t: T,
993                 _u: U,
994             }
995 
996             test!(#[repr(C)] (; Nested<u8, AU64>) => Some(0));
997             test!(#[repr(C)] (; Nested<u8, [AU64]>) => Some(0));
998             test!(#[repr(C)] (u8; Nested<u8, AU64>) => Some(8));
999             test!(#[repr(C)] (u8; Nested<u8, [AU64]>) => Some(8));
1000 
1001             // Test that `packed(N)` limits the offset of the trailing field.
1002             test!(#[repr(C, packed(        1))] (u8; elain::Align<        2>) => Some(        1));
1003             test!(#[repr(C, packed(        2))] (u8; elain::Align<        4>) => Some(        2));
1004             test!(#[repr(C, packed(        4))] (u8; elain::Align<        8>) => Some(        4));
1005             test!(#[repr(C, packed(        8))] (u8; elain::Align<       16>) => Some(        8));
1006             test!(#[repr(C, packed(       16))] (u8; elain::Align<       32>) => Some(       16));
1007             test!(#[repr(C, packed(       32))] (u8; elain::Align<       64>) => Some(       32));
1008             test!(#[repr(C, packed(       64))] (u8; elain::Align<      128>) => Some(       64));
1009             test!(#[repr(C, packed(      128))] (u8; elain::Align<      256>) => Some(      128));
1010             test!(#[repr(C, packed(      256))] (u8; elain::Align<      512>) => Some(      256));
1011             test!(#[repr(C, packed(      512))] (u8; elain::Align<     1024>) => Some(      512));
1012             test!(#[repr(C, packed(     1024))] (u8; elain::Align<     2048>) => Some(     1024));
1013             test!(#[repr(C, packed(     2048))] (u8; elain::Align<     4096>) => Some(     2048));
1014             test!(#[repr(C, packed(     4096))] (u8; elain::Align<     8192>) => Some(     4096));
1015             test!(#[repr(C, packed(     8192))] (u8; elain::Align<    16384>) => Some(     8192));
1016             test!(#[repr(C, packed(    16384))] (u8; elain::Align<    32768>) => Some(    16384));
1017             test!(#[repr(C, packed(    32768))] (u8; elain::Align<    65536>) => Some(    32768));
1018             test!(#[repr(C, packed(    65536))] (u8; elain::Align<   131072>) => Some(    65536));
1019             /* Alignments above 65536 are not yet supported.
1020             test!(#[repr(C, packed(   131072))] (u8; elain::Align<   262144>) => Some(   131072));
1021             test!(#[repr(C, packed(   262144))] (u8; elain::Align<   524288>) => Some(   262144));
1022             test!(#[repr(C, packed(   524288))] (u8; elain::Align<  1048576>) => Some(   524288));
1023             test!(#[repr(C, packed(  1048576))] (u8; elain::Align<  2097152>) => Some(  1048576));
1024             test!(#[repr(C, packed(  2097152))] (u8; elain::Align<  4194304>) => Some(  2097152));
1025             test!(#[repr(C, packed(  4194304))] (u8; elain::Align<  8388608>) => Some(  4194304));
1026             test!(#[repr(C, packed(  8388608))] (u8; elain::Align< 16777216>) => Some(  8388608));
1027             test!(#[repr(C, packed( 16777216))] (u8; elain::Align< 33554432>) => Some( 16777216));
1028             test!(#[repr(C, packed( 33554432))] (u8; elain::Align< 67108864>) => Some( 33554432));
1029             test!(#[repr(C, packed( 67108864))] (u8; elain::Align< 33554432>) => Some( 67108864));
1030             test!(#[repr(C, packed( 33554432))] (u8; elain::Align<134217728>) => Some( 33554432));
1031             test!(#[repr(C, packed(134217728))] (u8; elain::Align<268435456>) => Some(134217728));
1032             test!(#[repr(C, packed(268435456))] (u8; elain::Align<268435456>) => Some(268435456));
1033             */
1034 
1035             // Test that `align(N)` does not limit the offset of the trailing field.
1036             test!(#[repr(C, align(        1))] (u8; elain::Align<        2>) => Some(        2));
1037             test!(#[repr(C, align(        2))] (u8; elain::Align<        4>) => Some(        4));
1038             test!(#[repr(C, align(        4))] (u8; elain::Align<        8>) => Some(        8));
1039             test!(#[repr(C, align(        8))] (u8; elain::Align<       16>) => Some(       16));
1040             test!(#[repr(C, align(       16))] (u8; elain::Align<       32>) => Some(       32));
1041             test!(#[repr(C, align(       32))] (u8; elain::Align<       64>) => Some(       64));
1042             test!(#[repr(C, align(       64))] (u8; elain::Align<      128>) => Some(      128));
1043             test!(#[repr(C, align(      128))] (u8; elain::Align<      256>) => Some(      256));
1044             test!(#[repr(C, align(      256))] (u8; elain::Align<      512>) => Some(      512));
1045             test!(#[repr(C, align(      512))] (u8; elain::Align<     1024>) => Some(     1024));
1046             test!(#[repr(C, align(     1024))] (u8; elain::Align<     2048>) => Some(     2048));
1047             test!(#[repr(C, align(     2048))] (u8; elain::Align<     4096>) => Some(     4096));
1048             test!(#[repr(C, align(     4096))] (u8; elain::Align<     8192>) => Some(     8192));
1049             test!(#[repr(C, align(     8192))] (u8; elain::Align<    16384>) => Some(    16384));
1050             test!(#[repr(C, align(    16384))] (u8; elain::Align<    32768>) => Some(    32768));
1051             test!(#[repr(C, align(    32768))] (u8; elain::Align<    65536>) => Some(    65536));
1052             /* Alignments above 65536 are not yet supported.
1053             test!(#[repr(C, align(    65536))] (u8; elain::Align<   131072>) => Some(   131072));
1054             test!(#[repr(C, align(   131072))] (u8; elain::Align<   262144>) => Some(   262144));
1055             test!(#[repr(C, align(   262144))] (u8; elain::Align<   524288>) => Some(   524288));
1056             test!(#[repr(C, align(   524288))] (u8; elain::Align<  1048576>) => Some(  1048576));
1057             test!(#[repr(C, align(  1048576))] (u8; elain::Align<  2097152>) => Some(  2097152));
1058             test!(#[repr(C, align(  2097152))] (u8; elain::Align<  4194304>) => Some(  4194304));
1059             test!(#[repr(C, align(  4194304))] (u8; elain::Align<  8388608>) => Some(  8388608));
1060             test!(#[repr(C, align(  8388608))] (u8; elain::Align< 16777216>) => Some( 16777216));
1061             test!(#[repr(C, align( 16777216))] (u8; elain::Align< 33554432>) => Some( 33554432));
1062             test!(#[repr(C, align( 33554432))] (u8; elain::Align< 67108864>) => Some( 67108864));
1063             test!(#[repr(C, align( 67108864))] (u8; elain::Align< 33554432>) => Some( 33554432));
1064             test!(#[repr(C, align( 33554432))] (u8; elain::Align<134217728>) => Some(134217728));
1065             test!(#[repr(C, align(134217728))] (u8; elain::Align<268435456>) => Some(268435456));
1066             */
1067         }
1068 
1069         // FIXME(#29), FIXME(https://github.com/rust-lang/rust/issues/69835):
1070         // Remove this `cfg` when `size_of_val_raw` is stabilized.
1071         #[allow(clippy::decimal_literal_representation)]
1072         #[test]
1073         fn test_align_of_dst() {
1074             // Test that `align_of!` correctly computes the alignment of DSTs.
1075             assert_eq!(align_of!([elain::Align<1>]), Some(1));
1076             assert_eq!(align_of!([elain::Align<2>]), Some(2));
1077             assert_eq!(align_of!([elain::Align<4>]), Some(4));
1078             assert_eq!(align_of!([elain::Align<8>]), Some(8));
1079             assert_eq!(align_of!([elain::Align<16>]), Some(16));
1080             assert_eq!(align_of!([elain::Align<32>]), Some(32));
1081             assert_eq!(align_of!([elain::Align<64>]), Some(64));
1082             assert_eq!(align_of!([elain::Align<128>]), Some(128));
1083             assert_eq!(align_of!([elain::Align<256>]), Some(256));
1084             assert_eq!(align_of!([elain::Align<512>]), Some(512));
1085             assert_eq!(align_of!([elain::Align<1024>]), Some(1024));
1086             assert_eq!(align_of!([elain::Align<2048>]), Some(2048));
1087             assert_eq!(align_of!([elain::Align<4096>]), Some(4096));
1088             assert_eq!(align_of!([elain::Align<8192>]), Some(8192));
1089             assert_eq!(align_of!([elain::Align<16384>]), Some(16384));
1090             assert_eq!(align_of!([elain::Align<32768>]), Some(32768));
1091             assert_eq!(align_of!([elain::Align<65536>]), Some(65536));
1092             /* Alignments above 65536 are not yet supported.
1093             assert_eq!(align_of!([elain::Align<131072>]), Some(131072));
1094             assert_eq!(align_of!([elain::Align<262144>]), Some(262144));
1095             assert_eq!(align_of!([elain::Align<524288>]), Some(524288));
1096             assert_eq!(align_of!([elain::Align<1048576>]), Some(1048576));
1097             assert_eq!(align_of!([elain::Align<2097152>]), Some(2097152));
1098             assert_eq!(align_of!([elain::Align<4194304>]), Some(4194304));
1099             assert_eq!(align_of!([elain::Align<8388608>]), Some(8388608));
1100             assert_eq!(align_of!([elain::Align<16777216>]), Some(16777216));
1101             assert_eq!(align_of!([elain::Align<33554432>]), Some(33554432));
1102             assert_eq!(align_of!([elain::Align<67108864>]), Some(67108864));
1103             assert_eq!(align_of!([elain::Align<33554432>]), Some(33554432));
1104             assert_eq!(align_of!([elain::Align<134217728>]), Some(134217728));
1105             assert_eq!(align_of!([elain::Align<268435456>]), Some(268435456));
1106             */
1107         }
1108     }
1109 
1110     #[test]
1111     fn test_enum_casts() {
1112         // Test that casting the variants of enums with signed integer reprs to
1113         // unsigned integers obeys expected signed -> unsigned casting rules.
1114 
1115         #[repr(i8)]
1116         enum ReprI8 {
1117             MinusOne = -1,
1118             Zero = 0,
1119             Min = i8::MIN,
1120             Max = i8::MAX,
1121         }
1122 
1123         #[allow(clippy::as_conversions)]
1124         let x = ReprI8::MinusOne as u8;
1125         assert_eq!(x, u8::MAX);
1126 
1127         #[allow(clippy::as_conversions)]
1128         let x = ReprI8::Zero as u8;
1129         assert_eq!(x, 0);
1130 
1131         #[allow(clippy::as_conversions)]
1132         let x = ReprI8::Min as u8;
1133         assert_eq!(x, 128);
1134 
1135         #[allow(clippy::as_conversions)]
1136         let x = ReprI8::Max as u8;
1137         assert_eq!(x, 127);
1138     }
1139 
1140     #[test]
1141     fn test_struct_padding() {
1142         // Test that, for each provided repr, `struct_padding!` reports the
1143         // expected value.
1144         macro_rules! test {
1145             (#[$cfg:meta] ($($ts:ty),*) => $expect:expr) => {{
1146                 #[$cfg]
1147                 #[allow(dead_code)]
1148                 struct Test($($ts),*);
1149                 assert_eq!(struct_padding!(Test, None::<NonZeroUsize>, None::<NonZeroUsize>, [$($ts),*]), $expect);
1150             }};
1151             (#[$cfg:meta] $(#[$cfgs:meta])* ($($ts:ty),*) => $expect:expr) => {
1152                 test!(#[$cfg] ($($ts),*) => $expect);
1153                 test!($(#[$cfgs])* ($($ts),*) => $expect);
1154             };
1155         }
1156 
1157         test!(#[repr(C)] #[repr(transparent)] #[repr(packed)] () => 0);
1158         test!(#[repr(C)] #[repr(transparent)] #[repr(packed)] (u8) => 0);
1159         test!(#[repr(C)] #[repr(transparent)] #[repr(packed)] (u8, ()) => 0);
1160         test!(#[repr(C)] #[repr(packed)] (u8, u8) => 0);
1161 
1162         test!(#[repr(C)] (u8, AU64) => 7);
1163         // Rust won't let you put `#[repr(packed)]` on a type which contains a
1164         // `#[repr(align(n > 1))]` type (`AU64`), so we have to use `u64` here.
1165         // It's not ideal, but it definitely has align > 1 on /some/ of our CI
1166         // targets, and this isn't a particularly complex macro we're testing
1167         // anyway.
1168         test!(#[repr(packed)] (u8, u64) => 0);
1169     }
1170 
1171     #[test]
1172     fn test_repr_c_struct_padding() {
1173         // Test that, for each provided repr, `repr_c_struct_padding!` reports
1174         // the expected value.
1175         macro_rules! test {
1176             (($($ts:tt),*) => $expect:expr) => {{
1177                 #[repr(C)]
1178                 #[allow(dead_code)]
1179                 struct Test($($ts),*);
1180                 assert_eq!(repr_c_struct_has_padding!(Test, None::<NonZeroUsize>, None::<NonZeroUsize>, [$($ts),*]), $expect);
1181             }};
1182         }
1183 
1184         // Test static padding
1185         test!(() => false);
1186         test!(([u8]) => false);
1187         test!((u8) => false);
1188         test!((u8, [u8]) => false);
1189         test!((u8, ()) => false);
1190         test!((u8, (), [u8]) => false);
1191         test!((u8, u8) => false);
1192         test!((u8, u8, [u8]) => false);
1193 
1194         test!((u8, AU64) => true);
1195         test!((u8, AU64, [u8]) => true);
1196 
1197         // Test dynamic padding
1198         test!((AU64, [AU64]) => false);
1199         test!((u8, [AU64]) => true);
1200 
1201         #[repr(align(4))]
1202         struct AU32(#[allow(unused)] u32);
1203         test!((AU64, [AU64]) => false);
1204         test!((AU64, [AU32]) => true);
1205     }
1206 
1207     #[test]
1208     fn test_union_padding() {
1209         // Test that, for each provided repr, `union_padding!` reports the
1210         // expected value.
1211         macro_rules! test {
1212             (#[$cfg:meta] {$($fs:ident: $ts:ty),*} => $expect:expr) => {{
1213                 #[$cfg]
1214                 #[allow(unused)] // fields are never read
1215                 union Test{ $($fs: $ts),* }
1216                 assert_eq!(union_padding!(Test, None::<NonZeroUsize>, None::<usize>, [$($ts),*]), $expect);
1217             }};
1218             (#[$cfg:meta] $(#[$cfgs:meta])* {$($fs:ident: $ts:ty),*} => $expect:expr) => {
1219                 test!(#[$cfg] {$($fs: $ts),*} => $expect);
1220                 test!($(#[$cfgs])* {$($fs: $ts),*} => $expect);
1221             };
1222         }
1223 
1224         test!(#[repr(C)] #[repr(packed)] {a: u8} => 0);
1225         test!(#[repr(C)] #[repr(packed)] {a: u8, b: u8} => 0);
1226 
1227         // Rust won't let you put `#[repr(packed)]` on a type which contains a
1228         // `#[repr(align(n > 1))]` type (`AU64`), so we have to use `u64` here.
1229         // It's not ideal, but it definitely has align > 1 on /some/ of our CI
1230         // targets, and this isn't a particularly complex macro we're testing
1231         // anyway.
1232         test!(#[repr(C)] #[repr(packed)] {a: u8, b: u64} => 7);
1233     }
1234 
1235     #[test]
1236     fn test_enum_padding() {
1237         // Test that, for each provided repr, `enum_has_padding!` reports the
1238         // expected value.
1239         macro_rules! test {
1240             (#[repr($disc:ident $(, $c:ident)?)] { $($vs:ident ($($ts:ty),*),)* } => $expect:expr) => {
1241                 test!(@case #[repr($disc $(, $c)?)] { $($vs ($($ts),*),)* } => $expect);
1242             };
1243             (#[repr($disc:ident $(, $c:ident)?)] #[$cfg:meta] $(#[$cfgs:meta])* { $($vs:ident ($($ts:ty),*),)* } => $expect:expr) => {
1244                 test!(@case #[repr($disc $(, $c)?)] #[$cfg] { $($vs ($($ts),*),)* } => $expect);
1245                 test!(#[repr($disc $(, $c)?)] $(#[$cfgs])* { $($vs ($($ts),*),)* } => $expect);
1246             };
1247             (@case #[repr($disc:ident $(, $c:ident)?)] $(#[$cfg:meta])? { $($vs:ident ($($ts:ty),*),)* } => $expect:expr) => {{
1248                 #[repr($disc $(, $c)?)]
1249                 $(#[$cfg])?
1250                 #[allow(unused)] // variants and fields are never used
1251                 enum Test {
1252                     $($vs ($($ts),*),)*
1253                 }
1254                 assert_eq!(
1255                     enum_padding!(Test, None::<NonZeroUsize>, None::<NonZeroUsize>, $disc, $([$($ts),*]),*),
1256                     $expect
1257                 );
1258             }};
1259         }
1260 
1261         #[allow(unused)]
1262         #[repr(align(2))]
1263         struct U16(u16);
1264 
1265         #[allow(unused)]
1266         #[repr(align(4))]
1267         struct U32(u32);
1268 
1269         test!(#[repr(u8)] #[repr(C)] {
1270             A(u8),
1271         } => 0);
1272         test!(#[repr(u16)] #[repr(C)] {
1273             A(u8, u8),
1274             B(U16),
1275         } => 0);
1276         test!(#[repr(u32)] #[repr(C)] {
1277             A(u8, u8, u8, u8),
1278             B(U16, u8, u8),
1279             C(u8, u8, U16),
1280             D(U16, U16),
1281             E(U32),
1282         } => 0);
1283 
1284         // `repr(int)` can pack the discriminant more efficiently
1285         test!(#[repr(u8)] {
1286             A(u8, U16),
1287         } => 0);
1288         test!(#[repr(u8)] {
1289             A(u8, U16, U32),
1290         } => 0);
1291 
1292         // `repr(C)` cannot
1293         test!(#[repr(u8, C)] {
1294             A(u8, U16),
1295         } => 2);
1296         test!(#[repr(u8, C)] {
1297             A(u8, u8, u8, U32),
1298         } => 4);
1299 
1300         // And field ordering can always cause problems
1301         test!(#[repr(u8)] #[repr(C)] {
1302             A(U16, u8),
1303         } => 2);
1304         test!(#[repr(u8)] #[repr(C)] {
1305             A(U32, u8, u8, u8),
1306         } => 4);
1307     }
1308 }
1309