Skip to main content

zerocopy/util/
macros.rs

1// SPDX-License-Identifier: (BSD-2-Clause OR Apache-2.0) OR MIT
2//
3// Copyright 2023 The Fuchsia Authors
4//
5// Licensed under a BSD-style license <LICENSE-BSD>, Apache License, Version 2.0
6// <LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0>, or the MIT
7// license <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your option.
8// This file may not be copied, modified, or distributed except according to
9// those terms.
10
11/// Unsafely implements trait(s) for a type.
12///
13/// # Safety
14///
15/// The trait impl must be sound.
16///
17/// When implementing `TryFromBytes`:
18/// - If no `is_safe` impl is provided, then it must be valid for `is_safe` to
19///   unconditionally return `true`. In other words, it must be the case that any
20///   initialized sequence of bytes constitutes a valid instance of `$ty`.
21/// - If an `is_safe` impl is provided, then the impl of `is_safe` must only
22///   return `true` if its argument refers to a valid `$ty`.
23macro_rules! unsafe_impl {
24    // Implement `$trait` for `$ty` with no bounds.
25    ($(#[$attr:meta])* $ty:ty: $trait:ident $(; |$candidate:ident| $is_safe:expr)?) => {{
26        crate::util::macros::__unsafe();
27
28        $(#[$attr])*
29        // SAFETY: The caller promises that this is sound.
30        unsafe impl $trait for $ty {
31            unsafe_impl!(@method $trait $(; |$candidate| $is_safe)?);
32        }
33    }};
34
35    // Implement all `$traits` for `$ty` with no bounds.
36    //
37    // The 2 arms under this one are there so we can apply
38    // N attributes for each one of M trait implementations.
39    // The simple solution of:
40    //
41    // ($(#[$attrs:meta])* $ty:ty: $($traits:ident),*) => {
42    //     $( unsafe_impl!( $(#[$attrs])* $ty: $traits ) );*
43    // }
44    //
45    // Won't work. The macro processor sees that the outer repetition
46    // contains both $attrs and $traits and expects them to match the same
47    // amount of fragments.
48    //
49    // To solve this we must:
50    // 1. Pack the attributes into a single token tree fragment we can match over.
51    // 2. Expand the traits.
52    // 3. Unpack and expand the attributes.
53    ($(#[$attrs:meta])* $ty:ty: $($traits:ident),*) => {
54        unsafe_impl!(@impl_traits_with_packed_attrs { $(#[$attrs])* } $ty: $($traits),*)
55    };
56
57    (@impl_traits_with_packed_attrs $attrs:tt $ty:ty: $($traits:ident),*) => {{
58        $( unsafe_impl!(@unpack_attrs $attrs $ty: $traits); )*
59    }};
60
61    (@unpack_attrs { $(#[$attrs:meta])* } $ty:ty: $traits:ident) => {
62        unsafe_impl!($(#[$attrs])* $ty: $traits);
63    };
64
65    // This arm is identical to the following one, except it contains a
66    // preceding `const`. If we attempt to handle these with a single arm, there
67    // is an inherent ambiguity between `const` (the keyword) and `const` (the
68    // ident match for `$tyvar:ident`).
69    //
70    // To explain how this works, consider the following invocation:
71    //
72    //   unsafe_impl!(const N: usize, T: ?Sized + Copy => Clone for Foo<T>);
73    //
74    // In this invocation, here are the assignments to meta-variables:
75    //
76    //   |---------------|------------|
77    //   | Meta-variable | Assignment |
78    //   |---------------|------------|
79    //   | $constname    |  N         |
80    //   | $constty      |  usize     |
81    //   | $tyvar        |  T         |
82    //   | $optbound     |  Sized     |
83    //   | $bound        |  Copy      |
84    //   | $trait        |  Clone     |
85    //   | $ty           |  Foo<T>    |
86    //   |---------------|------------|
87    //
88    // The following arm has the same behavior with the exception of the lack of
89    // support for a leading `const` parameter.
90    (
91        $(#[$attr:meta])*
92        const $constname:ident : $constty:ident $(,)?
93        $($tyvar:ident $(: $(? $optbound:ident $(+)?)* $($bound:ident $(+)?)* )?),*
94        => $trait:ident for $ty:ty $(; |$candidate:ident| $is_safe:expr)?
95    ) => {
96        unsafe_impl!(
97            @inner
98            $(#[$attr])*
99            @const $constname: $constty,
100            $($tyvar $(: $(? $optbound +)* + $($bound +)*)?,)*
101            => $trait for $ty $(; |$candidate| $is_safe)?
102        );
103    };
104    (
105        $(#[$attr:meta])*
106        $($tyvar:ident $(: $(? $optbound:ident $(+)?)* $($bound:ident $(+)?)* )?),*
107        => $trait:ident for $ty:ty $(; |$candidate:ident| $is_safe:expr)?
108    ) => {{
109        unsafe_impl!(
110            @inner
111            $(#[$attr])*
112            $($tyvar $(: $(? $optbound +)* + $($bound +)*)?,)*
113            => $trait for $ty $(; |$candidate| $is_safe)?
114        );
115    }};
116    (
117        @inner
118        $(#[$attr:meta])*
119        $(@const $constname:ident : $constty:ident,)*
120        $($tyvar:ident $(: $(? $optbound:ident +)* + $($bound:ident +)* )?,)*
121        => $trait:ident for $ty:ty $(; |$candidate:ident| $is_safe:expr)?
122    ) => {{
123        crate::util::macros::__unsafe();
124
125        $(#[$attr])*
126        #[allow(non_local_definitions)]
127        // SAFETY: The caller promises that this is sound.
128        unsafe impl<$($tyvar $(: $(? $optbound +)* $($bound +)*)?),* $(, const $constname: $constty,)*> $trait for $ty {
129            unsafe_impl!(@method $trait $(; |$candidate| $is_safe)?);
130        }
131    }};
132
133    (@method TryFromBytes ; |$candidate:ident| $is_safe:expr) => {
134        #[allow(clippy::missing_inline_in_public_items, dead_code)]
135        #[cfg_attr(all(coverage_nightly, __ZEROCOPY_INTERNAL_USE_ONLY_NIGHTLY_FEATURES_IN_TESTS), coverage(off))]
136        fn only_derive_is_allowed_to_implement_this_trait() {}
137
138        #[inline]
139        fn is_safe<Alignment>($candidate: Maybe<'_, Self, Alignment>) -> bool
140        where
141            Alignment: crate::invariant::Alignment,
142        {
143            $is_safe
144        }
145    };
146    (@method TryFromBytes) => {
147        #[allow(clippy::missing_inline_in_public_items)]
148        #[cfg_attr(all(coverage_nightly, __ZEROCOPY_INTERNAL_USE_ONLY_NIGHTLY_FEATURES_IN_TESTS), coverage(off))]
149        fn only_derive_is_allowed_to_implement_this_trait() {}
150        #[inline(always)]
151        fn is_safe<Alignment>(_candidate: Maybe<'_, Self, Alignment>) -> bool
152        where
153            Alignment: crate::invariant::Alignment,
154        {
155            true
156        }
157    };
158    (@method $trait:ident) => {
159        #[allow(clippy::missing_inline_in_public_items, dead_code)]
160        #[cfg_attr(all(coverage_nightly, __ZEROCOPY_INTERNAL_USE_ONLY_NIGHTLY_FEATURES_IN_TESTS), coverage(off))]
161        fn only_derive_is_allowed_to_implement_this_trait() {}
162    };
163    (@method $trait:ident; |$_candidate:ident| $_is_safe:expr) => {
164        compile_error!("Can't provide `is_safe` impl for trait other than `TryFromBytes`");
165    };
166}
167
168/// Implements `$trait` for `$ty` where `$ty: TransmuteFrom<$repr>` (and
169/// vice-versa).
170///
171/// This macro is intended to be safe to call. The current proof is incomplete;
172/// see FIXME(#3691) below.
173macro_rules! impl_for_transmute_from {
174    (
175        $(#[$attr:meta])*
176        $($tyvar:ident $(: $(? $optbound:ident $(+)?)* $($bound:ident $(+)?)* )?)?
177        => $trait:ident for $ty:ty [$repr:ty]
178    ) => {
179        const _: () = {
180            $(#[$attr])*
181            #[allow(non_local_definitions)]
182
183            // SAFETY: `is_trait<T, R>` (defined and used below) requires
184            // reciprocal `TransmuteFrom<_, Safe, Safe>` bounds and `R: $trait`.
185            // If `T` and `R` have the same size, the reciprocal bounds imply
186            // that they permit the same `Safe` bit patterns. The call below
187            // instantiates `T` with `$ty` and `R` with `$repr`, and establishes
188            // `$repr: $trait`. The supported traits - `TryFromBytes`,
189            // `FromZeros`, `FromBytes`, and `IntoBytes` - are defined only in
190            // terms of bit validity, so these premises are sufficient when
191            // `$ty` and `$repr` have the same size.
192            //
193            // FIXME(#3691): This macro does not establish that `$ty` and
194            // `$repr` have the same size. Without that premise, `TransmuteFrom`
195            // conveys no safety guarantee, so these bounds do not make
196            // arbitrary invocations of this macro sound.
197            unsafe impl<$($tyvar $(: $(? $optbound +)* $($bound +)*)?)?> $trait for $ty {
198                #[allow(dead_code, clippy::missing_inline_in_public_items)]
199                #[cfg_attr(all(coverage_nightly, __ZEROCOPY_INTERNAL_USE_ONLY_NIGHTLY_FEATURES_IN_TESTS), coverage(off))]
200                fn only_derive_is_allowed_to_implement_this_trait() {
201                    use crate::pointer::{*, invariant::Safe};
202
203                    impl_for_transmute_from!(@assert_is_supported_trait $trait);
204
205                    fn is_trait<T, R>()
206                    where
207                        T: TransmuteFrom<R, Safe, Safe> + ?Sized,
208                        R: TransmuteFrom<T, Safe, Safe> + ?Sized,
209                        R: $trait,
210                    {
211                    }
212
213                    #[cfg_attr(all(coverage_nightly, __ZEROCOPY_INTERNAL_USE_ONLY_NIGHTLY_FEATURES_IN_TESTS), coverage(off))]
214                    fn f<$($tyvar $(: $(? $optbound +)* $($bound +)*)?)?>() {
215                        is_trait::<$ty, $repr>();
216                    }
217                }
218
219                impl_for_transmute_from!(
220                    @is_safe
221                    $(<$tyvar $(: $(? $optbound +)* $($bound +)*)?>)?
222                    $trait for $ty [$repr]
223                );
224            }
225        };
226    };
227    (@assert_is_supported_trait TryFromBytes) => {};
228    (@assert_is_supported_trait FromZeros) => {};
229    (@assert_is_supported_trait FromBytes) => {};
230    (@assert_is_supported_trait IntoBytes) => {};
231    (
232        @is_safe
233        $(<$tyvar:ident $(: $(? $optbound:ident $(+)?)* $($bound:ident $(+)?)* )?>)?
234        TryFromBytes for $ty:ty [$repr:ty]
235    ) => {
236        #[inline(always)]
237        fn is_safe<Alignment>(candidate: $crate::Maybe<'_, Self, Alignment>) -> bool
238        where
239            Alignment: $crate::invariant::Alignment,
240        {
241            // SAFETY: This macro ensures that `$repr` and `Self` have the same
242            // size and bit validity. Thus, a bit-valid instance of `$repr` is
243            // also a bit-valid instance of `Self`.
244            <$repr as TryFromBytes>::is_safe(candidate.transmute::<_, _, BecauseImmutable>())
245        }
246    };
247    (
248        @is_safe
249        $(<$tyvar:ident $(: $(? $optbound:ident $(+)?)* $($bound:ident $(+)?)* )?>)?
250        $trait:ident for $ty:ty [$repr:ty]
251    ) => {
252        // Trait other than `TryFromBytes`; no `is_safe` impl.
253    };
254}
255
256/// Implements a trait for a type, bounding on each member of the power set of
257/// a set of type variables. This is useful for implementing traits for tuples
258/// or `fn` types.
259///
260/// The last argument is the name of a macro which will be called in every
261/// `impl` block, and is expected to expand to the name of the type for which to
262/// implement the trait.
263///
264/// For example, the invocation:
265/// ```ignore
266/// unsafe_impl_for_power_set!(A, B => Foo for type!(...))
267/// ```
268/// ...expands to:
269/// ```ignore
270/// unsafe impl       Foo for type!()     { ... }
271/// unsafe impl<B>    Foo for type!(B)    { ... }
272/// unsafe impl<A, B> Foo for type!(A, B) { ... }
273/// ```
274macro_rules! unsafe_impl_for_power_set {
275    (
276        $first:ident $(, $rest:ident)* $(-> $ret:ident)? => $trait:ident for $macro:ident!(...)
277        $(; |$candidate:ident| $is_safe:expr)?
278    ) => {
279        unsafe_impl_for_power_set!(
280            $($rest),* $(-> $ret)? => $trait for $macro!(...)
281            $(; |$candidate| $is_safe)?
282        );
283        unsafe_impl_for_power_set!(
284            @impl $first $(, $rest)* $(-> $ret)? => $trait for $macro!(...)
285            $(; |$candidate| $is_safe)?
286        );
287    };
288    (
289        $(-> $ret:ident)? => $trait:ident for $macro:ident!(...)
290        $(; |$candidate:ident| $is_safe:expr)?
291    ) => {
292        unsafe_impl_for_power_set!(
293            @impl $(-> $ret)? => $trait for $macro!(...)
294            $(; |$candidate| $is_safe)?
295        );
296    };
297    (
298        @impl $($vars:ident),* $(-> $ret:ident)? => $trait:ident for $macro:ident!(...)
299        $(; |$candidate:ident| $is_safe:expr)?
300    ) => {
301        unsafe_impl!(
302            $($vars,)* $($ret)? => $trait for $macro!($($vars),* $(-> $ret)?)
303            $(; |$candidate| $is_safe)?
304        );
305    };
306}
307
308/// Expands to an `Option<extern "C" fn>` type with the given argument types and
309/// return type. Designed for use with `unsafe_impl_for_power_set`.
310macro_rules! opt_extern_c_fn {
311    ($($args:ident),* -> $ret:ident) => { Option<extern "C" fn($($args),*) -> $ret> };
312}
313
314/// Expands to an `Option<unsafe extern "C" fn>` type with the given argument
315/// types and return type. Designed for use with `unsafe_impl_for_power_set`.
316macro_rules! opt_unsafe_extern_c_fn {
317    ($($args:ident),* -> $ret:ident) => { Option<unsafe extern "C" fn($($args),*) -> $ret> };
318}
319
320/// Expands to an `Option<fn>` type with the given argument types and return
321/// type. Designed for use with `unsafe_impl_for_power_set`.
322macro_rules! opt_fn {
323    ($($args:ident),* -> $ret:ident) => { Option<fn($($args),*) -> $ret> };
324}
325
326/// Expands to an `Option<unsafe fn>` type with the given argument types and
327/// return type. Designed for use with `unsafe_impl_for_power_set`.
328macro_rules! opt_unsafe_fn {
329    ($($args:ident),* -> $ret:ident) => { Option<unsafe fn($($args),*) -> $ret> };
330}
331
332// This `allow` is needed because, when testing, we export this macro so it can
333// be used in `doctests`.
334#[allow(rustdoc::private_intra_doc_links)]
335/// Implements trait(s) for a type or verifies the given implementation by
336/// referencing an existing (derived) implementation.
337///
338/// This macro exists so that we can provide zerocopy-derive as an optional
339/// dependency and still get the benefit of using its derives to validate that
340/// our trait impls are sound.
341///
342/// When compiling without `--cfg 'feature = "derive"` and without `--cfg test`,
343/// `impl_or_verify!` emits the provided trait impl. When compiling with either
344/// of those cfgs, it is expected that the type in question is deriving the
345/// traits instead. In this case, `impl_or_verify!` emits code which validates
346/// that the given trait impl is at least as restrictive as the the impl emitted
347/// by the custom derive. This has the effect of confirming that the impl which
348/// is emitted when the `derive` feature is disabled is actually sound (on the
349/// assumption that the impl emitted by the custom derive is sound).
350///
351/// The caller is still required to provide a safety comment (e.g. using the
352/// `const _: () = unsafe` macro). The reason for this restriction is that,
353/// while `impl_or_verify!` can guarantee that the provided impl is sound when
354/// it is compiled with the appropriate cfgs, there is no way to guarantee that
355/// it is ever compiled with those cfgs. In particular, it would be possible to
356/// accidentally place an `impl_or_verify!` call in a context that is only ever
357/// compiled when the `derive` feature is disabled. If that were to happen,
358/// there would be nothing to prevent an unsound trait impl from being emitted.
359/// Requiring a safety comment reduces the likelihood of emitting an unsound
360/// impl in this case, and also provides useful documentation for readers of the
361/// code.
362///
363/// Finally, if a `TryFromBytes::is_safe` impl is provided, it must adhere to the
364/// safety preconditions of [`unsafe_impl!`].
365///
366/// ## Example
367///
368/// ```rust,ignore
369/// // Note that these derives are gated by `feature = "derive"`
370/// #[cfg_attr(any(feature = "derive", test), derive(FromZeros, FromBytes, IntoBytes, Unaligned))]
371/// #[repr(transparent)]
372/// struct Wrapper<T>(T);
373///
374/// const _: () = unsafe {
375///     /// SAFETY:
376///     /// `Wrapper<T>` is `repr(transparent)`, so it is sound to implement any
377///     /// zerocopy trait if `T` implements that trait.
378///     impl_or_verify!(T: FromZeros => FromZeros for Wrapper<T>);
379///     impl_or_verify!(T: FromBytes => FromBytes for Wrapper<T>);
380///     impl_or_verify!(T: IntoBytes => IntoBytes for Wrapper<T>);
381///     impl_or_verify!(T: Unaligned => Unaligned for Wrapper<T>);
382/// }
383/// ```
384#[cfg_attr(__ZEROCOPY_INTERNAL_USE_ONLY_DEV_MODE, macro_export)] // Used in `doctests.rs`
385#[doc(hidden)]
386macro_rules! impl_or_verify {
387    // The following two match arms follow the same pattern as their
388    // counterparts in `unsafe_impl!`; see the documentation on those arms for
389    // more details.
390    (
391        const $constname:ident : $constty:ident $(,)?
392        $($tyvar:ident $(: $(? $optbound:ident $(+)?)* $($bound:ident $(+)?)* )?),*
393        => $trait:ident for $ty:ty
394    ) => {
395        impl_or_verify!(@impl { unsafe_impl!(
396            const $constname: $constty, $($tyvar $(: $(? $optbound +)* $($bound +)*)?),* => $trait for $ty
397        ); });
398        impl_or_verify!(@verify $trait, {
399            impl<const $constname: $constty, $($tyvar $(: $(? $optbound +)* $($bound +)*)?),*> Subtrait for $ty {}
400        });
401    };
402    (
403        $($tyvar:ident $(: $(? $optbound:ident $(+)?)* $($bound:ident $(+)?)* )?),*
404        => $trait:ident for $ty:ty $(; |$candidate:ident| $is_safe:expr)?
405    ) => {
406        impl_or_verify!(@impl { unsafe_impl!(
407            $($tyvar $(: $(? $optbound +)* $($bound +)*)?),* => $trait for $ty
408            $(; |$candidate| $is_safe)?
409        ); });
410        impl_or_verify!(@verify $trait, {
411            impl<$($tyvar $(: $(? $optbound +)* $($bound +)*)?),*> Subtrait for $ty {}
412        });
413    };
414    (@impl $impl_block:tt) => {
415        #[cfg(not(any(feature = "derive", test)))]
416        { $impl_block };
417    };
418    (@verify $trait:ident, $impl_block:tt) => {
419        #[cfg(any(feature = "derive", test))]
420        {
421            // On some toolchains, `Subtrait` triggers the `dead_code` lint
422            // because it is implemented but never used.
423            #[allow(dead_code)]
424            trait Subtrait: $trait {}
425            $impl_block
426        };
427    };
428}
429
430/// Implements `KnownLayout` for a sized type.
431macro_rules! impl_known_layout {
432    ($(const $constvar:ident : $constty:ty, $tyvar:ident $(: ?$optbound:ident)? => $ty:ty),* $(,)?) => {
433        $(impl_known_layout!(@inner const $constvar: $constty, $tyvar $(: ?$optbound)? => $ty);)*
434    };
435    ($($tyvar:ident $(: ?$optbound:ident)? => $ty:ty),* $(,)?) => {
436        $(impl_known_layout!(@inner , $tyvar $(: ?$optbound)? => $ty);)*
437    };
438    ($($(#[$attrs:meta])* $ty:ty),*) => { $(impl_known_layout!(@inner , => $(#[$attrs])* $ty);)* };
439    (@inner $(const $constvar:ident : $constty:ty)? , $($tyvar:ident $(: ?$optbound:ident)?)? => $(#[$attrs:meta])* $ty:ty) => {
440        const _: () = {
441            use core::ptr::NonNull;
442
443            #[allow(non_local_definitions)]
444            $(#[$attrs])*
445            // SAFETY: Delegates safety to `DstLayout::for_type`.
446            unsafe impl<$($tyvar $(: ?$optbound)?)? $(, const $constvar : $constty)?> KnownLayout for $ty {
447                #[allow(clippy::missing_inline_in_public_items)]
448                #[cfg_attr(all(coverage_nightly, __ZEROCOPY_INTERNAL_USE_ONLY_NIGHTLY_FEATURES_IN_TESTS), coverage(off))]
449                fn only_derive_is_allowed_to_implement_this_trait() where Self: Sized {}
450
451                type PointerMetadata = ();
452
453                // SAFETY: `CoreMaybeUninit<T>::LAYOUT` and `T::LAYOUT` are
454                // identical because `CoreMaybeUninit<T>` has the same size and
455                // alignment as `T` [1], and `CoreMaybeUninit` admits
456                // uninitialized bytes in all positions.
457                //
458                // [1] Per https://doc.rust-lang.org/1.81.0/std/mem/union.MaybeUninit.html#layout-1:
459                //
460                //   `MaybeUninit<T>` is guaranteed to have the same size,
461                //   alignment, and ABI as `T`
462                type MaybeUninit = core::mem::MaybeUninit<Self>;
463
464                const LAYOUT: crate::DstLayout = crate::DstLayout::for_type::<$ty>();
465
466                // SAFETY: `.cast` preserves address and provenance.
467                //
468                // FIXME(#429): Add documentation to `.cast` that promises that
469                // it preserves provenance.
470                #[inline(always)]
471                fn raw_from_ptr_len(bytes: NonNull<u8>, _meta: ()) -> NonNull<Self> {
472                    bytes.cast::<Self>()
473                }
474
475                #[inline(always)]
476                fn pointer_to_metadata(_ptr: *mut Self) -> () {
477                }
478            }
479        };
480    };
481}
482
483/// Implements `KnownLayout` for a type in terms of the implementation of
484/// another type with the same representation.
485///
486/// # Safety
487///
488/// - `$ty` and `$repr` must have the same:
489///   - Fixed prefix size
490///   - Alignment
491///   - (For DSTs) trailing slice element size
492/// - It must be valid to perform an `as` cast from `*mut $repr` to `*mut $ty`,
493///   and this operation must preserve referent size (ie, `size_of_val_raw`).
494macro_rules! unsafe_impl_known_layout {
495    ($($tyvar:ident: ?Sized + KnownLayout =>)? #[repr($repr:ty)] $ty:ty) => {{
496        use core::ptr::NonNull;
497
498        crate::util::macros::__unsafe();
499
500        #[allow(non_local_definitions)]
501        // SAFETY: The caller promises that this is sound.
502        unsafe impl<$($tyvar: ?Sized + KnownLayout)?> KnownLayout for $ty {
503            #[allow(dead_code, clippy::missing_inline_in_public_items)]
504            #[cfg_attr(all(coverage_nightly, __ZEROCOPY_INTERNAL_USE_ONLY_NIGHTLY_FEATURES_IN_TESTS), coverage(off))]
505            fn only_derive_is_allowed_to_implement_this_trait() {}
506
507            type PointerMetadata = <$repr as KnownLayout>::PointerMetadata;
508            type MaybeUninit = <$repr as KnownLayout>::MaybeUninit;
509
510            const LAYOUT: DstLayout = <$repr as KnownLayout>::LAYOUT;
511
512            // SAFETY: All operations preserve address and provenance. Caller
513            // has promised that the `as` cast preserves size.
514            //
515            // FIXME(#429): Add documentation to `NonNull::new_unchecked` that
516            // it preserves provenance.
517            #[inline(always)]
518            fn raw_from_ptr_len(bytes: NonNull<u8>, meta: <$repr as KnownLayout>::PointerMetadata) -> NonNull<Self> {
519                #[allow(clippy::as_conversions)]
520                let ptr = <$repr>::raw_from_ptr_len(bytes, meta).as_ptr() as *mut Self;
521                // SAFETY: `ptr` was converted from `bytes`, which is non-null.
522                unsafe { NonNull::new_unchecked(ptr) }
523            }
524
525            #[inline(always)]
526            fn pointer_to_metadata(ptr: *mut Self) -> Self::PointerMetadata {
527                #[allow(clippy::as_conversions)]
528                let ptr = ptr as *mut $repr;
529                <$repr>::pointer_to_metadata(ptr)
530            }
531        }
532    }};
533}
534
535/// Uses `align_of` to confirm that a type or set of types have alignment 1.
536///
537/// Note that `align_of<T>` requires `T: Sized`, so this macro doesn't work for
538/// unsized types.
539macro_rules! assert_unaligned {
540    ($($tys:ty),*) => {
541        $(
542            // We only compile this assertion under `cfg(test)` to avoid taking
543            // an extra non-dev dependency (and making this crate more expensive
544            // to compile for our dependents).
545            #[cfg(test)]
546            static_assertions::const_assert_eq!(core::mem::align_of::<$tys>(), 1);
547        )*
548    };
549}
550
551/// Emits a function definition as either `const fn` or `fn` depending on
552/// whether the current toolchain version supports `const fn` with generic trait
553/// bounds.
554macro_rules! maybe_const_trait_bounded_fn {
555    // This case handles both `self` methods (where `self` is by value) and
556    // non-method functions. Each `$args` may optionally be followed by `:
557    // $arg_tys:ty`, which can be omitted for `self`.
558    ($(#[$attr:meta])* $vis:vis const fn $name:ident($($args:ident $(: $arg_tys:ty)?),* $(,)?) $(-> $ret_ty:ty)? $body:block) => {
559        #[cfg(not(no_zerocopy_generic_bounds_in_const_fn_1_61_0))]
560        $(#[$attr])* $vis const fn $name($($args $(: $arg_tys)?),*) $(-> $ret_ty)? $body
561
562        #[cfg(no_zerocopy_generic_bounds_in_const_fn_1_61_0)]
563        $(#[$attr])* $vis fn $name($($args $(: $arg_tys)?),*) $(-> $ret_ty)? $body
564    };
565}
566
567/// Either panic (if the current Rust toolchain supports panicking in `const
568/// fn`) or evaluate a constant that will cause an array indexing error whose
569/// error message will include the format string.
570///
571/// The type that this expression evaluates to must be `Copy`, or else the
572/// non-panicking desugaring will fail to compile.
573macro_rules! const_panic {
574    (@non_panic $($_arg:tt)+) => {{
575        // This will type check to whatever type is expected based on the call
576        // site.
577        let panic: [_; 0] = [];
578        // This will always fail (since we're indexing into an array of size 0.
579        #[allow(unconditional_panic)]
580        panic[0]
581    }};
582    ($($arg:tt)+) => {{
583        #[cfg(not(no_zerocopy_panic_in_const_and_vec_try_reserve_1_57_0))]
584        panic!($($arg)+);
585        #[cfg(no_zerocopy_panic_in_const_and_vec_try_reserve_1_57_0)]
586        const_panic!(@non_panic $($arg)+)
587    }};
588}
589
590/// Either assert (if the current Rust toolchain supports panicking in `const
591/// fn`) or evaluate the expression and, if it evaluates to `false`, call
592/// `const_panic!`. This is used in place of `assert!` in const contexts to
593/// accommodate old toolchains.
594macro_rules! const_assert {
595    ($e:expr) => {{
596        #[cfg(not(no_zerocopy_panic_in_const_and_vec_try_reserve_1_57_0))]
597        assert!($e);
598        #[cfg(no_zerocopy_panic_in_const_and_vec_try_reserve_1_57_0)]
599        {
600            let e = $e;
601            if !e {
602                let _: () = const_panic!(@non_panic concat!("assertion failed: ", stringify!($e)));
603            }
604        }
605    }};
606    ($e:expr, $($args:tt)+) => {{
607        #[cfg(not(no_zerocopy_panic_in_const_and_vec_try_reserve_1_57_0))]
608        assert!($e, $($args)+);
609        #[cfg(no_zerocopy_panic_in_const_and_vec_try_reserve_1_57_0)]
610        {
611            let e = $e;
612            if !e {
613                let _: () = const_panic!(@non_panic concat!("assertion failed: ", stringify!($e), ": ", stringify!($arg)), $($args)*);
614            }
615        }
616    }};
617}
618
619/// Like `const_assert!`, but relative to `debug_assert!`.
620macro_rules! const_debug_assert {
621    ($e:expr $(, $msg:expr)?) => {{
622        #[cfg(not(no_zerocopy_panic_in_const_and_vec_try_reserve_1_57_0))]
623        debug_assert!($e $(, $msg)?);
624        #[cfg(no_zerocopy_panic_in_const_and_vec_try_reserve_1_57_0)]
625        {
626            // Use this (rather than `#[cfg(debug_assertions)]`) to ensure that
627            // `$e` is always compiled even if it will never be evaluated at
628            // runtime.
629            if cfg!(debug_assertions) {
630                let e = $e;
631                if !e {
632                    let _: () = const_panic!(@non_panic concat!("assertion failed: ", stringify!($e) $(, ": ", $msg)?));
633                }
634            }
635        }
636    }}
637}
638
639/// Either invoke `unreachable!()` or `loop {}` depending on whether the Rust
640/// toolchain supports panicking in `const fn`.
641macro_rules! const_unreachable {
642    () => {{
643        #[cfg(not(no_zerocopy_panic_in_const_and_vec_try_reserve_1_57_0))]
644        unreachable!();
645
646        #[cfg(no_zerocopy_panic_in_const_and_vec_try_reserve_1_57_0)]
647        loop {}
648    }};
649}
650
651/// Asserts at compile time that `$condition` is true for `Self` or the given
652/// `$tyvar`s. Unlike `const_assert`, this is *strictly* a compile-time check;
653/// it cannot be evaluated in a runtime context. The condition is checked after
654/// monomorphization and, upon failure, emits a compile error.
655macro_rules! static_assert {
656    (Self $(: $(? $optbound:ident $(+)?)* $($bound:ident $(+)?)* )? => $condition:expr $(, $args:tt)*) => {{
657        trait StaticAssert {
658            const ASSERT: bool;
659        }
660
661        impl<T $(: $(? $optbound +)* $($bound +)*)?> StaticAssert for T {
662            const ASSERT: bool = {
663                const_assert!($condition $(, $args)*);
664                $condition
665            };
666        }
667
668        const_assert!(<Self as StaticAssert>::ASSERT);
669    }};
670    ($($tyvar:ident $(: $(? $optbound:ident $(+)?)* $($bound:ident $(+)?)* )?),* => $condition:expr $(, $args:tt)*) => {{
671        trait StaticAssert {
672            const ASSERT: bool;
673        }
674
675        // NOTE: We use `PhantomData` so we can support unsized types.
676        impl<$($tyvar $(: $(? $optbound +)* $($bound +)*)?,)*> StaticAssert for ($(core::marker::PhantomData<$tyvar>,)*) {
677            const ASSERT: bool = {
678                const_assert!($condition $(, $args)*);
679                $condition
680            };
681        }
682
683        const_assert!(<($(core::marker::PhantomData<$tyvar>,)*) as StaticAssert>::ASSERT);
684    }};
685}
686
687/// Assert at compile time that `tyvar` does not have a zero-sized DST
688/// component.
689macro_rules! static_assert_dst_is_not_zst {
690    ($tyvar:ident) => {{
691        use crate::KnownLayout;
692        static_assert!($tyvar: ?Sized + KnownLayout => {
693            let dst_is_zst = match $tyvar::LAYOUT.size_info {
694                crate::SizeInfo::Sized { .. } => false,
695                crate::SizeInfo::SliceDst(TrailingSliceLayout { elem_size, .. }) => {
696                    elem_size == 0
697                }
698            };
699            !dst_is_zst
700        }, "cannot call this method on a dynamically-sized type whose trailing slice element is zero-sized");
701    }}
702}
703
704/// Defines a named [`Cast`] implementation.
705///
706/// # Safety
707///
708/// The caller must ensure that, given `src: *mut $src`, `src as *mut $dst` is a
709/// size-preserving or size-shrinking cast.
710///
711/// [`Cast`]: crate::pointer::cast::Cast
712#[macro_export]
713#[doc(hidden)]
714macro_rules! define_cast {
715    // We require the caller to provide an `unsafe` block as part of the input
716    // syntax since a call to `define_cast!` is useless inside of an `unsafe`
717    // block (since it would introduce a type which can't be named outside of
718    // the context of that block).
719    (unsafe { $vis:vis $name:ident $(<$tyvar:ident $(: ?$optbound:ident)?>)? = $src:ty => $dst:ty }) => {
720        #[allow(missing_debug_implementations, missing_copy_implementations, unreachable_pub)]
721        $vis enum $name {}
722
723        // SAFETY: The caller promises that `src as *mut $src` is a size-
724        // preserving or size-shrinking cast. All operations preserve
725        // provenance.
726        unsafe impl $(<$tyvar $(: ?$optbound)?>)? $crate::pointer::cast::Project<$src, $dst> for $name {
727            fn project(src: $crate::pointer::PtrInner<'_, $src>) -> *mut $dst {
728                #[allow(clippy::as_conversions)]
729                return src.as_ptr() as *mut $dst;
730            }
731        }
732
733        // SAFETY: The impl of `Project::project` preserves referent address.
734        unsafe impl $(<$tyvar $(: ?$optbound)?>)? $crate::pointer::cast::Cast<$src, $dst> for $name {}
735    };
736}
737
738/// Implements `TransmuteFrom` and `SizeEq` for `T` and `$wrapper<T>`.
739///
740/// # Safety
741///
742/// `T` and `$wrapper<T>` must have the same bit validity, and must have the
743/// same size in the sense of `CastExact` (specifically, both a
744/// `T`-to-`$wrapper<T>` cast and a `$wrapper<T>`-to-`T` cast must be
745/// size-preserving).
746macro_rules! unsafe_impl_for_transparent_wrapper {
747    ($vis:vis T $(: ?$optbound:ident)? => $wrapper:ident<T>) => {{
748        crate::util::macros::__unsafe();
749
750        use crate::pointer::{TransmuteFrom, cast::{CastExact, TransitiveProject}, SizeEq, invariant::Safe};
751        use crate::wrappers::ReadOnly;
752
753        // SAFETY: The caller promises that `T` and `$wrapper<T>` have the same
754        // bit validity.
755        unsafe impl<T $(: ?$optbound)?> TransmuteFrom<T, Safe, Safe> for $wrapper<T> {}
756        // SAFETY: See previous safety comment.
757        unsafe impl<T $(: ?$optbound)?> TransmuteFrom<$wrapper<T>, Safe, Safe> for T {}
758        // SAFETY: The caller promises that a `T` to `$wrapper<T>` cast is
759        // size-preserving.
760        define_cast!(unsafe { $vis CastToWrapper<T $(: ?$optbound)? > = T => $wrapper<T> });
761        // SAFETY: The caller promises that a `T` to `$wrapper<T>` cast is
762        // size-preserving.
763        unsafe impl<T $(: ?$optbound)?> CastExact<T, $wrapper<T>> for CastToWrapper {}
764        // SAFETY: The caller promises that a `$wrapper<T>` to `T` cast is
765        // size-preserving.
766        define_cast!(unsafe { $vis CastFromWrapper<T $(: ?$optbound)? > = $wrapper<T> => T });
767        // SAFETY: The caller promises that a `$wrapper<T>` to `T` cast is
768        // size-preserving.
769        unsafe impl<T $(: ?$optbound)?> CastExact<$wrapper<T>, T> for CastFromWrapper {}
770
771        impl<T $(: ?$optbound)?> SizeEq<T> for $wrapper<T> {
772            type CastFrom = CastToWrapper;
773        }
774        impl<T $(: ?$optbound)?> SizeEq<$wrapper<T>> for T {
775            type CastFrom = CastFromWrapper;
776        }
777
778        impl<T $(: ?$optbound)?> SizeEq<ReadOnly<T>> for $wrapper<T> {
779            type CastFrom = TransitiveProject<
780                T,
781                <T as SizeEq<ReadOnly<T>>>::CastFrom,
782                CastToWrapper,
783            >;
784        }
785        impl<T $(: ?$optbound)?> SizeEq<$wrapper<T>> for ReadOnly<T> {
786            type CastFrom = TransitiveProject<
787                T,
788                CastFromWrapper,
789                <ReadOnly<T> as SizeEq<T>>::CastFrom,
790            >;
791        }
792
793        impl<T $(: ?$optbound)?> SizeEq<ReadOnly<T>> for ReadOnly<$wrapper<T>> {
794            type CastFrom = TransitiveProject<
795                $wrapper<T>,
796                <$wrapper<T> as SizeEq<ReadOnly<T>>>::CastFrom,
797                <ReadOnly<$wrapper<T>> as SizeEq<$wrapper<T>>>::CastFrom,
798            >;
799        }
800        impl<T $(: ?$optbound)?> SizeEq<ReadOnly<$wrapper<T>>> for ReadOnly<T> {
801            type CastFrom = TransitiveProject<
802                $wrapper<T>,
803                <$wrapper<T> as SizeEq<ReadOnly<$wrapper<T>>>>::CastFrom,
804                <ReadOnly<T> as SizeEq<$wrapper<T>>>::CastFrom,
805            >;
806        }
807    }};
808}
809
810macro_rules! impl_transitive_transmute_from {
811    ($($tyvar:ident $(: ?$optbound:ident)?)? => $t:ty => $u:ty => $v:ty) => {
812        const _: () = {
813            use crate::pointer::{TransmuteFrom, SizeEq, invariant::Safe};
814
815            impl<$($tyvar $(: ?$optbound)?)?> SizeEq<$t> for $v
816            where
817                $u: SizeEq<$t>,
818                $v: SizeEq<$u>,
819            {
820                type CastFrom = cast::TransitiveProject<
821                    $u,
822                    <$u as SizeEq<$t>>::CastFrom,
823                    <$v as SizeEq<$u>>::CastFrom
824                >;
825            }
826
827            // SAFETY: Since `$u: TransmuteFrom<$t, Safe, Safe>`, it is sound to
828            // transmute a bit-valid `$t` to a bit-valid `$u`. Since `$v:
829            // TransmuteFrom<$u, Safe, Safe>`, it is sound to transmute that
830            // bit-valid `$u` to a bit-valid `$v`.
831            unsafe impl<$($tyvar $(: ?$optbound)?)?> TransmuteFrom<$t, Safe, Safe> for $v
832            where
833                $u: TransmuteFrom<$t, Safe, Safe>,
834                $v: TransmuteFrom<$u, Safe, Safe>,
835            {}
836        };
837    };
838}
839
840/// A no-op `unsafe fn` for use in macro expansions.
841///
842/// Calling this function in a macro expansion ensures that the macro's caller
843/// must wrap the call in `unsafe { ... }`.
844#[inline(always)]
845pub(crate) const unsafe fn __unsafe() {}
846
847/// Extracts the contents of doc comments.
848#[allow(unused)]
849macro_rules! docstring {
850    ($(#[doc = $content:expr])*) => {
851        concat!($($content, "\n",)*)
852    }
853}
854
855/// Generate a rustdoc-style header with `$name` as the HTML ID for the 'Code
856/// Generation' section of documentation.
857#[allow(unused)]
858macro_rules! codegen_header {
859    ($level:expr, $name:expr) => {
860        concat!(
861            "
862<",
863            $level,
864            " id='method.",
865            $name,
866            ".codegen'>
867    <a class='doc-anchor' href='#method.",
868            $name,
869            ".codegen'>ยง</a>
870    Code Generation
871</",
872            $level,
873            ">
874"
875        )
876    };
877}
878
879/// Generates HTML tabs.
880#[rustfmt::skip]
881#[allow(unused)]
882macro_rules! tabs {
883    (
884        name = $name:expr,
885        arity = $arity:literal,
886        $([
887            $($open:ident)?
888            @index $n:literal
889            @title $title:literal
890            $(#[doc = $content:expr])*
891        ]),*
892    ) => {
893        concat!("
894<div class='codegen-tabs' style='--arity: ", $arity ,"'>", $(concat!("
895    <details name='tab-", $name,"' style='--n: ", $n ,"'", $(stringify!($open),)*">
896        <summary><h6>", $title, "</h6></summary>
897        <div>
898
899", $($content, "\n",)* "
900\
901        </div>
902    </details>"),)*
903"</div>")
904    }
905}
906
907/// Generates the HTML for a single benchmark example.
908#[allow(unused)]
909macro_rules! codegen_example {
910    (format = $format:expr, bench = $bench:expr) => {
911        tabs!(
912            name = $bench,
913            arity = 4,
914            [
915                @index 1
916                @title "Format"
917                /// ```ignore
918                #[doc = include_str!(concat!("../benches/formats/", $format, ".rs"))]
919                /// ```
920            ],
921            [
922                @index 2
923                @title "Benchmark"
924                /// ```ignore
925                #[doc = include_str!(concat!("../benches/", $bench, ".rs"))]
926                /// ```
927            ],
928            [
929                open
930                @index 3
931                @title "Assembly"
932                /// ```plain
933                #[doc = include_str!(concat!("../benches/", $bench, ".x86-64"))]
934                /// ```
935            ],
936            [
937                @index 4
938                @title "Machine Code Analysis"
939                /// ```plain
940                #[doc = include_str!(concat!("../benches/", $bench, ".x86-64.mca"))]
941                /// ```
942            ]
943        )
944    }
945}
946
947/// Generate the HTML for a suite of benchmark examples.
948#[allow(unused)]
949macro_rules! codegen_example_suite {
950    (
951        bench = $bench:expr,
952        format = $format:expr,
953        arity = $arity:literal,
954        $([
955            $($open:ident)?
956            @index $index:literal
957            @title $title:literal
958            @variant $variant:literal
959        ]),*
960    ) => {
961        tabs!(
962            name = $bench,
963            arity = $arity,
964            $([
965                $($open)*
966                @index $index
967                @title $title
968                #[doc = codegen_example!(
969                    format = concat!($format, "_", $variant),
970                    bench = concat!($bench, "_", $variant)
971                )]
972            ]),*
973        )
974    }
975}
976
977/// Generates the string for code generation preamble.
978#[allow(unused)]
979macro_rules! codegen_preamble {
980    () => {
981        docstring!(
982            ///
983            /// This abstraction is safe and cheap, but does not necessarily
984            /// have zero runtime cost. The codegen you experience in practice
985            /// will depend on optimization level, the layout of the destination
986            /// type, and what the compiler can prove about the source.
987            ///
988        )
989    }
990}
991
992/// Stub for rendering codegen documentation; used to break build dependency
993/// between benches and zerocopy when re-blessing codegen tests.
994#[allow(unused)]
995#[cfg(not(doc))]
996macro_rules! codegen_section {
997    (
998        header = $level:expr,
999        bench = $bench:expr,
1000        format = $format:expr,
1001        arity = $arity:literal,
1002        $([
1003            $($open:ident)?
1004            @index $index:literal
1005            @title $title:literal
1006            @variant $variant:literal
1007        ]),*
1008    ) => {
1009        ""
1010    };
1011    (
1012        header = $level:expr,
1013        bench = $bench:expr,
1014        format = $format:expr,
1015    ) => {
1016        ""
1017    };
1018}
1019
1020/// Generates the HTML for code generation documentation.
1021#[allow(unused)]
1022#[cfg(doc)]
1023macro_rules! codegen_section {
1024    (
1025        header = $level:expr,
1026        bench = $bench:expr,
1027        format = $format:expr,
1028        arity = $arity:literal,
1029        $([
1030            $($open:ident)?
1031            @index $index:literal
1032            @title $title:literal
1033            @variant $variant:literal
1034        ]),*
1035    ) => {
1036        concat!(
1037            codegen_header!($level, $bench),
1038            codegen_preamble!(),
1039            docstring!(
1040                ///
1041                /// The below examples illustrate typical codegen for
1042                /// increasingly complex types:
1043                ///
1044            ),
1045            codegen_example_suite!(
1046                bench = $bench,
1047                format = $format,
1048                arity = $arity,
1049                $([
1050                    $($open)*
1051                    @index $index
1052                    @title $title
1053                    @variant $variant
1054                ]),*
1055            )
1056        )
1057    };
1058    (
1059        header = $level:expr,
1060        bench = $bench:expr,
1061        format = $format:expr,
1062    ) => {
1063        concat!(
1064            codegen_header!($level, $bench),
1065            codegen_preamble!(),
1066            codegen_example!(
1067                format = $format,
1068                bench = $bench
1069            )
1070        )
1071    }
1072}