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}