• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2023 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 /// Documents multiple unsafe blocks with a single safety comment.
10 ///
11 /// Invoked as:
12 ///
13 /// ```rust,ignore
14 /// safety_comment! {
15 ///     // Non-doc comments come first.
16 ///     /// SAFETY:
17 ///     /// Safety comment starts on its own line.
18 ///     macro_1!(args);
19 ///     macro_2! { args };
20 ///     /// SAFETY:
21 ///     /// Subsequent safety comments are allowed but not required.
22 ///     macro_3! { args };
23 /// }
24 /// ```
25 ///
26 /// The macro invocations are emitted, each decorated with the following
27 /// attribute: `#[allow(clippy::undocumented_unsafe_blocks)]`.
28 macro_rules! safety_comment {
29     (#[doc = r" SAFETY:"] $($(#[$attr:meta])* $macro:ident!$args:tt;)*) => {
30         #[allow(clippy::undocumented_unsafe_blocks, unused_attributes)]
31         const _: () = { $($(#[$attr])* $macro!$args;)* };
32     }
33 }
34 
35 /// Unsafely implements trait(s) for a type.
36 ///
37 /// # Safety
38 ///
39 /// The trait impl must be sound.
40 ///
41 /// When implementing `TryFromBytes`:
42 /// - If no `is_bit_valid` impl is provided, then it must be valid for
43 ///   `is_bit_valid` to unconditionally return `true`. In other words, it must
44 ///   be the case that any initialized sequence of bytes constitutes a valid
45 ///   instance of `$ty`.
46 /// - If an `is_bit_valid` impl is provided, then:
47 ///   - Regardless of whether the provided closure takes a `Ptr<$repr>` or
48 ///     `&$repr` argument, if `$ty` and `$repr` are different types, then it
49 ///     must be the case that, given `t: *mut $ty` and `let r = t as *mut
50 ///     $repr`:
51 ///     - `r` refers to an object of equal or lesser size than the object
52 ///       referred to by `t`.
53 ///     - `r` refers to an object with `UnsafeCell`s at the same byte ranges as
54 ///       the object referred to by `t`.
55 ///   - If the provided closure takes a `&$repr` argument, then given a `Ptr<'a,
56 ///     $ty>` which satisfies the preconditions of
57 ///     `TryFromBytes::<$ty>::is_bit_valid`, it must be guaranteed that the
58 ///     memory referenced by that `Ptr` always contains a valid `$repr`.
59 ///   - The impl of `is_bit_valid` must only return `true` for its argument
60 ///     `Ptr<$repr>` if the original `Ptr<$ty>` refers to a valid `$ty`.
61 macro_rules! unsafe_impl {
62     // Implement `$trait` for `$ty` with no bounds.
63     ($(#[$attr:meta])* $ty:ty: $trait:ident $(; |$candidate:ident: MaybeAligned<$repr:ty>| $is_bit_valid:expr)?) => {
64         $(#[$attr])*
65         unsafe impl $trait for $ty {
66             unsafe_impl!(@method $trait $(; |$candidate: MaybeAligned<$repr>| $is_bit_valid)?);
67         }
68     };
69 
70     // Implement all `$traits` for `$ty` with no bounds.
71     //
72     // The 2 arms under this one are there so we can apply
73     // N attributes for each one of M trait implementations.
74     // The simple solution of:
75     //
76     // ($(#[$attrs:meta])* $ty:ty: $($traits:ident),*) => {
77     //     $( unsafe_impl!( $(#[$attrs])* $ty: $traits ) );*
78     // }
79     //
80     // Won't work. The macro processor sees that the outer repetition
81     // contains both $attrs and $traits and expects them to match the same
82     // amount of fragments.
83     //
84     // To solve this we must:
85     // 1. Pack the attributes into a single token tree fragment we can match over.
86     // 2. Expand the traits.
87     // 3. Unpack and expand the attributes.
88     ($(#[$attrs:meta])* $ty:ty: $($traits:ident),*) => {
89         unsafe_impl!(@impl_traits_with_packed_attrs { $(#[$attrs])* } $ty: $($traits),*)
90     };
91 
92     (@impl_traits_with_packed_attrs $attrs:tt $ty:ty: $($traits:ident),*) => {
93         $( unsafe_impl!(@unpack_attrs $attrs $ty: $traits); )*
94     };
95 
96     (@unpack_attrs { $(#[$attrs:meta])* } $ty:ty: $traits:ident) => {
97         unsafe_impl!($(#[$attrs])* $ty: $traits);
98     };
99 
100     // This arm is identical to the following one, except it contains a
101     // preceding `const`. If we attempt to handle these with a single arm, there
102     // is an inherent ambiguity between `const` (the keyword) and `const` (the
103     // ident match for `$tyvar:ident`).
104     //
105     // To explain how this works, consider the following invocation:
106     //
107     //   unsafe_impl!(const N: usize, T: ?Sized + Copy => Clone for Foo<T>);
108     //
109     // In this invocation, here are the assignments to meta-variables:
110     //
111     //   |---------------|------------|
112     //   | Meta-variable | Assignment |
113     //   |---------------|------------|
114     //   | $constname    |  N         |
115     //   | $constty      |  usize     |
116     //   | $tyvar        |  T         |
117     //   | $optbound     |  Sized     |
118     //   | $bound        |  Copy      |
119     //   | $trait        |  Clone     |
120     //   | $ty           |  Foo<T>    |
121     //   |---------------|------------|
122     //
123     // The following arm has the same behavior with the exception of the lack of
124     // support for a leading `const` parameter.
125     (
126         $(#[$attr:meta])*
127         const $constname:ident : $constty:ident $(,)?
128         $($tyvar:ident $(: $(? $optbound:ident $(+)?)* $($bound:ident $(+)?)* )?),*
129         => $trait:ident for $ty:ty $(; |$candidate:ident $(: MaybeAligned<$ref_repr:ty>)? $(: Maybe<$ptr_repr:ty>)?| $is_bit_valid:expr)?
130     ) => {
131         unsafe_impl!(
132             @inner
133             $(#[$attr])*
134             @const $constname: $constty,
135             $($tyvar $(: $(? $optbound +)* + $($bound +)*)?,)*
136             => $trait for $ty $(; |$candidate $(: MaybeAligned<$ref_repr>)? $(: Maybe<$ptr_repr>)?| $is_bit_valid)?
137         );
138     };
139     (
140         $(#[$attr:meta])*
141         $($tyvar:ident $(: $(? $optbound:ident $(+)?)* $($bound:ident $(+)?)* )?),*
142         => $trait:ident for $ty:ty $(; |$candidate:ident $(: MaybeAligned<$ref_repr:ty>)? $(: Maybe<$ptr_repr:ty>)?| $is_bit_valid:expr)?
143     ) => {
144         unsafe_impl!(
145             @inner
146             $(#[$attr])*
147             $($tyvar $(: $(? $optbound +)* + $($bound +)*)?,)*
148             => $trait for $ty $(; |$candidate $(: MaybeAligned<$ref_repr>)? $(: Maybe<$ptr_repr>)?| $is_bit_valid)?
149         );
150     };
151     (
152         @inner
153         $(#[$attr:meta])*
154         $(@const $constname:ident : $constty:ident,)*
155         $($tyvar:ident $(: $(? $optbound:ident +)* + $($bound:ident +)* )?,)*
156         => $trait:ident for $ty:ty $(; |$candidate:ident $(: MaybeAligned<$ref_repr:ty>)? $(: Maybe<$ptr_repr:ty>)?| $is_bit_valid:expr)?
157     ) => {
158         $(#[$attr])*
159         #[allow(non_local_definitions)]
160         unsafe impl<$($tyvar $(: $(? $optbound +)* $($bound +)*)?),* $(, const $constname: $constty,)*> $trait for $ty {
161             unsafe_impl!(@method $trait $(; |$candidate: $(MaybeAligned<$ref_repr>)? $(Maybe<$ptr_repr>)?| $is_bit_valid)?);
162         }
163     };
164 
165     (@method TryFromBytes ; |$candidate:ident: MaybeAligned<$repr:ty>| $is_bit_valid:expr) => {
166         #[allow(clippy::missing_inline_in_public_items)]
167         #[cfg_attr(all(coverage_nightly, __ZEROCOPY_INTERNAL_USE_ONLY_NIGHTLY_FEATURES_IN_TESTS), coverage(off))]
168         fn only_derive_is_allowed_to_implement_this_trait() {}
169 
170         #[inline]
171         fn is_bit_valid<AA: crate::pointer::invariant::Reference>(candidate: Maybe<'_, Self, AA>) -> bool {
172             // SAFETY:
173             // - The cast preserves address. The caller has promised that the
174             //   cast results in an object of equal or lesser size, and so the
175             //   cast returns a pointer which references a subset of the bytes
176             //   of `p`.
177             // - The cast preserves provenance.
178             // - The caller has promised that the destination type has
179             //   `UnsafeCell`s at the same byte ranges as the source type.
180             #[allow(clippy::as_conversions)]
181             let candidate = unsafe { candidate.cast_unsized_unchecked::<$repr, _>(|p| p as *mut _) };
182 
183             // SAFETY: The caller has promised that the referenced memory region
184             // will contain a valid `$repr`.
185             let $candidate = unsafe { candidate.assume_validity::<crate::pointer::invariant::Valid>() };
186             $is_bit_valid
187         }
188     };
189     (@method TryFromBytes ; |$candidate:ident: Maybe<$repr:ty>| $is_bit_valid:expr) => {
190         #[allow(clippy::missing_inline_in_public_items)]
191         #[cfg_attr(all(coverage_nightly, __ZEROCOPY_INTERNAL_USE_ONLY_NIGHTLY_FEATURES_IN_TESTS), coverage(off))]
192         fn only_derive_is_allowed_to_implement_this_trait() {}
193 
194         #[inline]
195         fn is_bit_valid<AA: crate::pointer::invariant::Reference>(candidate: Maybe<'_, Self, AA>) -> bool {
196             // SAFETY:
197             // - The cast preserves address. The caller has promised that the
198             //   cast results in an object of equal or lesser size, and so the
199             //   cast returns a pointer which references a subset of the bytes
200             //   of `p`.
201             // - The cast preserves provenance.
202             // - The caller has promised that the destination type has
203             //   `UnsafeCell`s at the same byte ranges as the source type.
204             #[allow(clippy::as_conversions)]
205             let $candidate = unsafe { candidate.cast_unsized_unchecked::<$repr, _>(|p| p as *mut _) };
206 
207             // Restore the invariant that the referent bytes are initialized.
208             // SAFETY: The above cast does not uninitialize any referent bytes;
209             // they remain initialized.
210             let $candidate = unsafe { $candidate.assume_validity::<crate::pointer::invariant::Initialized>() };
211 
212             $is_bit_valid
213         }
214     };
215     (@method TryFromBytes) => {
216         #[allow(clippy::missing_inline_in_public_items)]
217         #[cfg_attr(all(coverage_nightly, __ZEROCOPY_INTERNAL_USE_ONLY_NIGHTLY_FEATURES_IN_TESTS), coverage(off))]
218         fn only_derive_is_allowed_to_implement_this_trait() {}
219         #[inline(always)] fn is_bit_valid<AA: crate::pointer::invariant::Reference>(_: Maybe<'_, Self, AA>) -> bool { true }
220     };
221     (@method $trait:ident) => {
222         #[allow(clippy::missing_inline_in_public_items)]
223         #[cfg_attr(all(coverage_nightly, __ZEROCOPY_INTERNAL_USE_ONLY_NIGHTLY_FEATURES_IN_TESTS), coverage(off))]
224         fn only_derive_is_allowed_to_implement_this_trait() {}
225     };
226     (@method $trait:ident; |$_candidate:ident $(: &$_ref_repr:ty)? $(: NonNull<$_ptr_repr:ty>)?| $_is_bit_valid:expr) => {
227         compile_error!("Can't provide `is_bit_valid` impl for trait other than `TryFromBytes`");
228     };
229 }
230 
231 /// Implements `$trait` for a type which implements `TransparentWrapper`.
232 ///
233 /// Calling this macro is safe; the internals of the macro emit appropriate
234 /// trait bounds which ensure that the given impl is sound.
235 macro_rules! impl_for_transparent_wrapper {
236     (
237         $(#[$attr:meta])*
238         $($tyvar:ident $(: $(? $optbound:ident $(+)?)* $($bound:ident $(+)?)* )?)?
239         => $trait:ident for $ty:ty $(; |$candidate:ident $(: MaybeAligned<$ref_repr:ty>)? $(: Maybe<$ptr_repr:ty>)?| $is_bit_valid:expr)?
240     ) => {
241         $(#[$attr])*
242         #[allow(non_local_definitions)]
243 
244         // This block implements `$trait` for `$ty` under the following
245         // conditions:
246         // - `$ty: TransparentWrapper`
247         // - `$ty::Inner: $trait`
248         // - For some `Xxx`, `$ty::XxxVariance = Covariant` (`Xxx` is determined
249         //   by the `@define_is_transparent_wrapper` macro arms). This bound
250         //   ensures that some layout property is the same between `$ty` and
251         //   `$ty::Inner`. Which layout property this is depends on the trait
252         //   being implemented (for example, `FromBytes` is not concerned with
253         //   alignment, but is concerned with bit validity).
254         //
255         // In other words, `$ty` is guaranteed to soundly implement `$trait`
256         // because some property of its layout is the same as `$ty::Inner`,
257         // which implements `$trait`. Most of the complexity in this macro is to
258         // ensure that the above-mentioned conditions are actually met, and that
259         // the proper variance (ie, the proper layout property) is chosen.
260 
261         // SAFETY:
262         // - `is_transparent_wrapper<I, W>` requires:
263         //   - `W: TransparentWrapper<I>`
264         //   - `W::Inner: $trait`
265         // - `f` is generic over `I: Invariants`, and in its body, calls
266         //   `is_transparent_wrapper::<I, $ty>()`. Thus, this code will only
267         //   compile if, for all `I: Invariants`:
268         //   - `$ty: TransparentWrapper<I>`
269         //   - `$ty::Inner: $trait`
270         //
271         // These two facts - that `$ty: TransparentWrapper<I>` and that
272         // `$ty::Inner: $trait` - are the preconditions to the full safety
273         // proofs, which are completed below in the
274         // `@define_is_transparent_wrapper` macro arms. The safety proof is
275         // slightly different for each trait.
276         unsafe impl<$($tyvar $(: $(? $optbound +)* $($bound +)*)?)?> $trait for $ty {
277             #[allow(dead_code, clippy::missing_inline_in_public_items)]
278             #[cfg_attr(all(coverage_nightly, __ZEROCOPY_INTERNAL_USE_ONLY_NIGHTLY_FEATURES_IN_TESTS), coverage(off))]
279             fn only_derive_is_allowed_to_implement_this_trait() {
280                 use crate::{pointer::invariant::Invariants, util::*};
281 
282                 impl_for_transparent_wrapper!(@define_is_transparent_wrapper $trait);
283 
284                 #[cfg_attr(all(coverage_nightly, __ZEROCOPY_INTERNAL_USE_ONLY_NIGHTLY_FEATURES_IN_TESTS), coverage(off))]
285                 fn f<I: Invariants, $($tyvar $(: $(? $optbound +)* $($bound +)*)?)?>() {
286                     is_transparent_wrapper::<I, $ty>();
287                 }
288             }
289 
290             impl_for_transparent_wrapper!(
291                 @is_bit_valid
292                 $(<$tyvar $(: $(? $optbound +)* $($bound +)*)?>)?
293                 $trait for $ty
294             );
295         }
296     };
297     (@define_is_transparent_wrapper Immutable) => {
298         // SAFETY: `W: TransparentWrapper<UnsafeCellVariance = Covariant>`
299         // requires that `W` has `UnsafeCell`s at the same byte offsets as
300         // `W::Inner`. `W::Inner: Immutable` implies that `W::Inner` does not
301         // contain any `UnsafeCell`s, and so `W` does not contain any
302         // `UnsafeCell`s. Since `W = $ty`, `$ty` can soundly implement
303         // `Immutable`.
304         impl_for_transparent_wrapper!(@define_is_transparent_wrapper Immutable, UnsafeCellVariance)
305     };
306     (@define_is_transparent_wrapper FromZeros) => {
307         // SAFETY: `W: TransparentWrapper<ValidityVariance = Covariant>`
308         // requires that `W` has the same bit validity as `W::Inner`. `W::Inner:
309         // FromZeros` implies that the all-zeros bit pattern is a bit-valid
310         // instance of `W::Inner`, and so the all-zeros bit pattern is a
311         // bit-valid instance of `W`. Since `W = $ty`, `$ty` can soundly
312         // implement `FromZeros`.
313         impl_for_transparent_wrapper!(@define_is_transparent_wrapper FromZeros, ValidityVariance)
314     };
315     (@define_is_transparent_wrapper FromBytes) => {
316         // SAFETY: `W: TransparentWrapper<ValidityVariance = Covariant>`
317         // requires that `W` has the same bit validity as `W::Inner`. `W::Inner:
318         // FromBytes` implies that any initialized bit pattern is a bit-valid
319         // instance of `W::Inner`, and so any initialized bit pattern is a
320         // bit-valid instance of `W`. Since `W = $ty`, `$ty` can soundly
321         // implement `FromBytes`.
322         impl_for_transparent_wrapper!(@define_is_transparent_wrapper FromBytes, ValidityVariance)
323     };
324     (@define_is_transparent_wrapper IntoBytes) => {
325         // SAFETY: `W: TransparentWrapper<ValidityVariance = Covariant>`
326         // requires that `W` has the same bit validity as `W::Inner`. `W::Inner:
327         // IntoBytes` implies that no bit-valid instance of `W::Inner` contains
328         // uninitialized bytes, and so no bit-valid instance of `W` contains
329         // uninitialized bytes. Since `W = $ty`, `$ty` can soundly implement
330         // `IntoBytes`.
331         impl_for_transparent_wrapper!(@define_is_transparent_wrapper IntoBytes, ValidityVariance)
332     };
333     (@define_is_transparent_wrapper Unaligned) => {
334         // SAFETY: `W: TransparentWrapper<AlignmentVariance = Covariant>`
335         // requires that `W` has the same alignment as `W::Inner`. `W::Inner:
336         // Unaligned` implies `W::Inner`'s alignment is 1, and so `W`'s
337         // alignment is 1. Since `W = $ty`, `W` can soundly implement
338         // `Unaligned`.
339         impl_for_transparent_wrapper!(@define_is_transparent_wrapper Unaligned, AlignmentVariance)
340     };
341     (@define_is_transparent_wrapper TryFromBytes) => {
342         // SAFETY: `W: TransparentWrapper<ValidityVariance = Covariant>`
343         // requires that `W` has the same bit validity as `W::Inner`. `W::Inner:
344         // TryFromBytes` implies that `<W::Inner as
345         // TryFromBytes>::is_bit_valid(c)` only returns `true` if `c` references
346         // a bit-valid instance of `W::Inner`. Thus, `<W::Inner as
347         // TryFromBytes>::is_bit_valid(c)` only returns `true` if `c` references
348         // a bit-valid instance of `W`. Below, we implement `<W as
349         // TryFromBytes>::is_bit_valid` by deferring to `<W::Inner as
350         // TryFromBytes>::is_bit_valid`. Since `W = $ty`, it is sound for `$ty`
351         // to implement `TryFromBytes` with this implementation of
352         // `is_bit_valid`.
353         impl_for_transparent_wrapper!(@define_is_transparent_wrapper TryFromBytes, ValidityVariance)
354     };
355     (@define_is_transparent_wrapper $trait:ident, $variance:ident) => {
356         #[cfg_attr(all(coverage_nightly, __ZEROCOPY_INTERNAL_USE_ONLY_NIGHTLY_FEATURES_IN_TESTS), coverage(off))]
357         fn is_transparent_wrapper<I: Invariants, W: TransparentWrapper<I, $variance = Covariant> + ?Sized>()
358         where
359             W::Inner: $trait,
360         {}
361     };
362     (
363         @is_bit_valid
364         $(<$tyvar:ident $(: $(? $optbound:ident $(+)?)* $($bound:ident $(+)?)* )?>)?
365         TryFromBytes for $ty:ty
366     ) => {
367         // SAFETY: See safety comment in `(@define_is_transparent_wrapper
368         // TryFromBytes)` macro arm for an explanation of why this is a sound
369         // implementation of `is_bit_valid`.
370         #[inline]
371         fn is_bit_valid<A: crate::pointer::invariant::Reference>(candidate: Maybe<'_, Self, A>) -> bool {
372             TryFromBytes::is_bit_valid(candidate.transparent_wrapper_into_inner())
373         }
374     };
375     (
376         @is_bit_valid
377         $(<$tyvar:ident $(: $(? $optbound:ident $(+)?)* $($bound:ident $(+)?)* )?>)?
378         $trait:ident for $ty:ty
379     ) => {
380         // Trait other than `TryFromBytes`; no `is_bit_valid` impl.
381     };
382 }
383 
384 /// Implements a trait for a type, bounding on each memeber of the power set of
385 /// a set of type variables. This is useful for implementing traits for tuples
386 /// or `fn` types.
387 ///
388 /// The last argument is the name of a macro which will be called in every
389 /// `impl` block, and is expected to expand to the name of the type for which to
390 /// implement the trait.
391 ///
392 /// For example, the invocation:
393 /// ```ignore
394 /// unsafe_impl_for_power_set!(A, B => Foo for type!(...))
395 /// ```
396 /// ...expands to:
397 /// ```ignore
398 /// unsafe impl       Foo for type!()     { ... }
399 /// unsafe impl<B>    Foo for type!(B)    { ... }
400 /// unsafe impl<A, B> Foo for type!(A, B) { ... }
401 /// ```
402 macro_rules! unsafe_impl_for_power_set {
403     (
404         $first:ident $(, $rest:ident)* $(-> $ret:ident)? => $trait:ident for $macro:ident!(...)
405         $(; |$candidate:ident $(: MaybeAligned<$ref_repr:ty>)? $(: Maybe<$ptr_repr:ty>)?| $is_bit_valid:expr)?
406     ) => {
407         unsafe_impl_for_power_set!(
408             $($rest),* $(-> $ret)? => $trait for $macro!(...)
409             $(; |$candidate $(: MaybeAligned<$ref_repr>)? $(: Maybe<$ptr_repr>)?| $is_bit_valid)?
410         );
411         unsafe_impl_for_power_set!(
412             @impl $first $(, $rest)* $(-> $ret)? => $trait for $macro!(...)
413             $(; |$candidate $(: MaybeAligned<$ref_repr>)? $(: Maybe<$ptr_repr>)?| $is_bit_valid)?
414         );
415     };
416     (
417         $(-> $ret:ident)? => $trait:ident for $macro:ident!(...)
418         $(; |$candidate:ident $(: MaybeAligned<$ref_repr:ty>)? $(: Maybe<$ptr_repr:ty>)?| $is_bit_valid:expr)?
419     ) => {
420         unsafe_impl_for_power_set!(
421             @impl $(-> $ret)? => $trait for $macro!(...)
422             $(; |$candidate $(: MaybeAligned<$ref_repr>)? $(: Maybe<$ptr_repr>)?| $is_bit_valid)?
423         );
424     };
425     (
426         @impl $($vars:ident),* $(-> $ret:ident)? => $trait:ident for $macro:ident!(...)
427         $(; |$candidate:ident $(: MaybeAligned<$ref_repr:ty>)? $(: Maybe<$ptr_repr:ty>)?| $is_bit_valid:expr)?
428     ) => {
429         unsafe_impl!(
430             $($vars,)* $($ret)? => $trait for $macro!($($vars),* $(-> $ret)?)
431             $(; |$candidate $(: MaybeAligned<$ref_repr>)? $(: Maybe<$ptr_repr>)?| $is_bit_valid)?
432         );
433     };
434 }
435 
436 /// Expands to an `Option<extern "C" fn>` type with the given argument types and
437 /// return type. Designed for use with `unsafe_impl_for_power_set`.
438 macro_rules! opt_extern_c_fn {
439     ($($args:ident),* -> $ret:ident) => { Option<extern "C" fn($($args),*) -> $ret> };
440 }
441 
442 /// Expands to a `Option<fn>` type with the given argument types and return
443 /// type. Designed for use with `unsafe_impl_for_power_set`.
444 macro_rules! opt_fn {
445     ($($args:ident),* -> $ret:ident) => { Option<fn($($args),*) -> $ret> };
446 }
447 
448 /// Implements trait(s) for a type or verifies the given implementation by
449 /// referencing an existing (derived) implementation.
450 ///
451 /// This macro exists so that we can provide zerocopy-derive as an optional
452 /// dependency and still get the benefit of using its derives to validate that
453 /// our trait impls are sound.
454 ///
455 /// When compiling without `--cfg 'feature = "derive"` and without `--cfg test`,
456 /// `impl_or_verify!` emits the provided trait impl. When compiling with either
457 /// of those cfgs, it is expected that the type in question is deriving the
458 /// traits instead. In this case, `impl_or_verify!` emits code which validates
459 /// that the given trait impl is at least as restrictive as the the impl emitted
460 /// by the custom derive. This has the effect of confirming that the impl which
461 /// is emitted when the `derive` feature is disabled is actually sound (on the
462 /// assumption that the impl emitted by the custom derive is sound).
463 ///
464 /// The caller is still required to provide a safety comment (e.g. using the
465 /// `safety_comment!` macro) . The reason for this restriction is that, while
466 /// `impl_or_verify!` can guarantee that the provided impl is sound when it is
467 /// compiled with the appropriate cfgs, there is no way to guarantee that it is
468 /// ever compiled with those cfgs. In particular, it would be possible to
469 /// accidentally place an `impl_or_verify!` call in a context that is only ever
470 /// compiled when the `derive` feature is disabled. If that were to happen,
471 /// there would be nothing to prevent an unsound trait impl from being emitted.
472 /// Requiring a safety comment reduces the likelihood of emitting an unsound
473 /// impl in this case, and also provides useful documentation for readers of the
474 /// code.
475 ///
476 /// Finally, if a `TryFromBytes::is_bit_valid` impl is provided, it must adhere
477 /// to the safety preconditions of [`unsafe_impl!`].
478 ///
479 /// ## Example
480 ///
481 /// ```rust,ignore
482 /// // Note that these derives are gated by `feature = "derive"`
483 /// #[cfg_attr(any(feature = "derive", test), derive(FromZeros, FromBytes, IntoBytes, Unaligned))]
484 /// #[repr(transparent)]
485 /// struct Wrapper<T>(T);
486 ///
487 /// safety_comment! {
488 ///     /// SAFETY:
489 ///     /// `Wrapper<T>` is `repr(transparent)`, so it is sound to implement any
490 ///     /// zerocopy trait if `T` implements that trait.
491 ///     impl_or_verify!(T: FromZeros => FromZeros for Wrapper<T>);
492 ///     impl_or_verify!(T: FromBytes => FromBytes for Wrapper<T>);
493 ///     impl_or_verify!(T: IntoBytes => IntoBytes for Wrapper<T>);
494 ///     impl_or_verify!(T: Unaligned => Unaligned for Wrapper<T>);
495 /// }
496 /// ```
497 macro_rules! impl_or_verify {
498     // The following two match arms follow the same pattern as their
499     // counterparts in `unsafe_impl!`; see the documentation on those arms for
500     // more details.
501     (
502         const $constname:ident : $constty:ident $(,)?
503         $($tyvar:ident $(: $(? $optbound:ident $(+)?)* $($bound:ident $(+)?)* )?),*
504         => $trait:ident for $ty:ty
505     ) => {
506         impl_or_verify!(@impl { unsafe_impl!(
507             const $constname: $constty, $($tyvar $(: $(? $optbound +)* $($bound +)*)?),* => $trait for $ty
508         ); });
509         impl_or_verify!(@verify $trait, {
510             impl<const $constname: $constty, $($tyvar $(: $(? $optbound +)* $($bound +)*)?),*> Subtrait for $ty {}
511         });
512     };
513     (
514         $($tyvar:ident $(: $(? $optbound:ident $(+)?)* $($bound:ident $(+)?)* )?),*
515         => $trait:ident for $ty:ty $(; |$candidate:ident $(: MaybeAligned<$ref_repr:ty>)? $(: Maybe<$ptr_repr:ty>)?| $is_bit_valid:expr)?
516     ) => {
517         impl_or_verify!(@impl { unsafe_impl!(
518             $($tyvar $(: $(? $optbound +)* $($bound +)*)?),* => $trait for $ty
519             $(; |$candidate $(: MaybeAligned<$ref_repr>)? $(: Maybe<$ptr_repr>)?| $is_bit_valid)?
520         ); });
521         impl_or_verify!(@verify $trait, {
522             impl<$($tyvar $(: $(? $optbound +)* $($bound +)*)?),*> Subtrait for $ty {}
523         });
524     };
525     (@impl $impl_block:tt) => {
526         #[cfg(not(any(feature = "derive", test)))]
527         const _: () = { $impl_block };
528     };
529     (@verify $trait:ident, $impl_block:tt) => {
530         #[cfg(any(feature = "derive", test))]
531         const _: () = {
532             trait Subtrait: $trait {}
533             $impl_block
534         };
535     };
536 }
537 
538 /// Implements `KnownLayout` for a sized type.
539 macro_rules! impl_known_layout {
540     ($(const $constvar:ident : $constty:ty, $tyvar:ident $(: ?$optbound:ident)? => $ty:ty),* $(,)?) => {
541         $(impl_known_layout!(@inner const $constvar: $constty, $tyvar $(: ?$optbound)? => $ty);)*
542     };
543     ($($tyvar:ident $(: ?$optbound:ident)? => $ty:ty),* $(,)?) => {
544         $(impl_known_layout!(@inner , $tyvar $(: ?$optbound)? => $ty);)*
545     };
546     ($($(#[$attrs:meta])* $ty:ty),*) => { $(impl_known_layout!(@inner , => $(#[$attrs])* $ty);)* };
547     (@inner $(const $constvar:ident : $constty:ty)? , $($tyvar:ident $(: ?$optbound:ident)?)? => $(#[$attrs:meta])* $ty:ty) => {
548         const _: () = {
549             use core::ptr::NonNull;
550 
551             #[allow(non_local_definitions)]
552             $(#[$attrs])*
553             // SAFETY: Delegates safety to `DstLayout::for_type`.
554             unsafe impl<$($tyvar $(: ?$optbound)?)? $(, const $constvar : $constty)?> KnownLayout for $ty {
555                 #[allow(clippy::missing_inline_in_public_items)]
556                 #[cfg_attr(all(coverage_nightly, __ZEROCOPY_INTERNAL_USE_ONLY_NIGHTLY_FEATURES_IN_TESTS), coverage(off))]
557                 fn only_derive_is_allowed_to_implement_this_trait() where Self: Sized {}
558 
559                 type PointerMetadata = ();
560 
561                 // SAFETY: `CoreMaybeUninit<T>::LAYOUT` and `T::LAYOUT` are
562                 // identical because `CoreMaybeUninit<T>` has the same size and
563                 // alignment as `T` [1], and `CoreMaybeUninit` admits
564                 // uninitialized bytes in all positions.
565                 //
566                 // [1] Per https://doc.rust-lang.org/1.81.0/std/mem/union.MaybeUninit.html#layout-1:
567                 //
568                 //   `MaybeUninit<T>` is guaranteed to have the same size,
569                 //   alignment, and ABI as `T`
570                 type MaybeUninit = core::mem::MaybeUninit<Self>;
571 
572                 const LAYOUT: crate::DstLayout = crate::DstLayout::for_type::<$ty>();
573 
574                 // SAFETY: `.cast` preserves address and provenance.
575                 //
576                 // TODO(#429): Add documentation to `.cast` that promises that
577                 // it preserves provenance.
578                 #[inline(always)]
579                 fn raw_from_ptr_len(bytes: NonNull<u8>, _meta: ()) -> NonNull<Self> {
580                     bytes.cast::<Self>()
581                 }
582 
583                 #[inline(always)]
584                 fn pointer_to_metadata(_ptr: *mut Self) -> () {
585                 }
586             }
587         };
588     };
589 }
590 
591 /// Implements `KnownLayout` for a type in terms of the implementation of
592 /// another type with the same representation.
593 ///
594 /// # Safety
595 ///
596 /// - `$ty` and `$repr` must have the same:
597 ///   - Fixed prefix size
598 ///   - Alignment
599 ///   - (For DSTs) trailing slice element size
600 /// - It must be valid to perform an `as` cast from `*mut $repr` to `*mut $ty`,
601 ///   and this operation must preserve referent size (ie, `size_of_val_raw`).
602 macro_rules! unsafe_impl_known_layout {
603     ($($tyvar:ident: ?Sized + KnownLayout =>)? #[repr($repr:ty)] $ty:ty) => {
604         const _: () = {
605             use core::ptr::NonNull;
606 
607             #[allow(non_local_definitions)]
608             unsafe impl<$($tyvar: ?Sized + KnownLayout)?> KnownLayout for $ty {
609                 #[allow(clippy::missing_inline_in_public_items)]
610                 #[cfg_attr(all(coverage_nightly, __ZEROCOPY_INTERNAL_USE_ONLY_NIGHTLY_FEATURES_IN_TESTS), coverage(off))]
611                 fn only_derive_is_allowed_to_implement_this_trait() {}
612 
613                 type PointerMetadata = <$repr as KnownLayout>::PointerMetadata;
614                 type MaybeUninit = <$repr as KnownLayout>::MaybeUninit;
615 
616                 const LAYOUT: DstLayout = <$repr as KnownLayout>::LAYOUT;
617 
618                 // SAFETY: All operations preserve address and provenance.
619                 // Caller has promised that the `as` cast preserves size.
620                 //
621                 // TODO(#429): Add documentation to `NonNull::new_unchecked`
622                 // that it preserves provenance.
623                 #[inline(always)]
624                 fn raw_from_ptr_len(bytes: NonNull<u8>, meta: <$repr as KnownLayout>::PointerMetadata) -> NonNull<Self> {
625                     #[allow(clippy::as_conversions)]
626                     let ptr = <$repr>::raw_from_ptr_len(bytes, meta).as_ptr() as *mut Self;
627                     // SAFETY: `ptr` was converted from `bytes`, which is non-null.
628                     unsafe { NonNull::new_unchecked(ptr) }
629                 }
630 
631                 #[inline(always)]
632                 fn pointer_to_metadata(ptr: *mut Self) -> Self::PointerMetadata {
633                     #[allow(clippy::as_conversions)]
634                     let ptr = ptr as *mut $repr;
635                     <$repr>::pointer_to_metadata(ptr)
636                 }
637             }
638         };
639     };
640 }
641 
642 /// Uses `align_of` to confirm that a type or set of types have alignment 1.
643 ///
644 /// Note that `align_of<T>` requires `T: Sized`, so this macro doesn't work for
645 /// unsized types.
646 macro_rules! assert_unaligned {
647     ($($tys:ty),*) => {
648         $(
649             // We only compile this assertion under `cfg(test)` to avoid taking
650             // an extra non-dev dependency (and making this crate more expensive
651             // to compile for our dependents).
652             #[cfg(test)]
653             static_assertions::const_assert_eq!(core::mem::align_of::<$tys>(), 1);
654         )*
655     };
656 }
657 
658 /// Emits a function definition as either `const fn` or `fn` depending on
659 /// whether the current toolchain version supports `const fn` with generic trait
660 /// bounds.
661 macro_rules! maybe_const_trait_bounded_fn {
662     // This case handles both `self` methods (where `self` is by value) and
663     // non-method functions. Each `$args` may optionally be followed by `:
664     // $arg_tys:ty`, which can be omitted for `self`.
665     ($(#[$attr:meta])* $vis:vis const fn $name:ident($($args:ident $(: $arg_tys:ty)?),* $(,)?) $(-> $ret_ty:ty)? $body:block) => {
666         #[cfg(zerocopy_generic_bounds_in_const_fn_1_61_0)]
667         $(#[$attr])* $vis const fn $name($($args $(: $arg_tys)?),*) $(-> $ret_ty)? $body
668 
669         #[cfg(not(zerocopy_generic_bounds_in_const_fn_1_61_0))]
670         $(#[$attr])* $vis fn $name($($args $(: $arg_tys)?),*) $(-> $ret_ty)? $body
671     };
672 }
673 
674 /// Either panic (if the current Rust toolchain supports panicking in `const
675 /// fn`) or evaluate a constant that will cause an array indexing error whose
676 /// error message will include the format string.
677 ///
678 /// The type that this expression evaluates to must be `Copy`, or else the
679 /// non-panicking desugaring will fail to compile.
680 macro_rules! const_panic {
681     (@non_panic $($_arg:tt)+) => {{
682         // This will type check to whatever type is expected based on the call
683         // site.
684         let panic: [_; 0] = [];
685         // This will always fail (since we're indexing into an array of size 0.
686         #[allow(unconditional_panic)]
687         panic[0]
688     }};
689     ($($arg:tt)+) => {{
690         #[cfg(zerocopy_panic_in_const_and_vec_try_reserve_1_57_0)]
691         panic!($($arg)+);
692         #[cfg(not(zerocopy_panic_in_const_and_vec_try_reserve_1_57_0))]
693         const_panic!(@non_panic $($arg)+)
694     }};
695 }
696 
697 /// Either assert (if the current Rust toolchain supports panicking in `const
698 /// fn`) or evaluate the expression and, if it evaluates to `false`, call
699 /// `const_panic!`. This is used in place of `assert!` in const contexts to
700 /// accommodate old toolchains.
701 macro_rules! const_assert {
702     ($e:expr) => {{
703         #[cfg(zerocopy_panic_in_const_and_vec_try_reserve_1_57_0)]
704         assert!($e);
705         #[cfg(not(zerocopy_panic_in_const_and_vec_try_reserve_1_57_0))]
706         {
707             let e = $e;
708             if !e {
709                 let _: () = const_panic!(@non_panic concat!("assertion failed: ", stringify!($e)));
710             }
711         }
712     }};
713     ($e:expr, $($args:tt)+) => {{
714         #[cfg(zerocopy_panic_in_const_and_vec_try_reserve_1_57_0)]
715         assert!($e, $($args)+);
716         #[cfg(not(zerocopy_panic_in_const_and_vec_try_reserve_1_57_0))]
717         {
718             let e = $e;
719             if !e {
720                 let _: () = const_panic!(@non_panic concat!("assertion failed: ", stringify!($e), ": ", stringify!($arg)), $($args)*);
721             }
722         }
723     }};
724 }
725 
726 /// Like `const_assert!`, but relative to `debug_assert!`.
727 macro_rules! const_debug_assert {
728     ($e:expr $(, $msg:expr)?) => {{
729         #[cfg(zerocopy_panic_in_const_and_vec_try_reserve_1_57_0)]
730         debug_assert!($e $(, $msg)?);
731         #[cfg(not(zerocopy_panic_in_const_and_vec_try_reserve_1_57_0))]
732         {
733             // Use this (rather than `#[cfg(debug_assertions)]`) to ensure that
734             // `$e` is always compiled even if it will never be evaluated at
735             // runtime.
736             if cfg!(debug_assertions) {
737                 let e = $e;
738                 if !e {
739                     let _: () = const_panic!(@non_panic concat!("assertion failed: ", stringify!($e) $(, ": ", $msg)?));
740                 }
741             }
742         }
743     }}
744 }
745 
746 /// Either invoke `unreachable!()` or `loop {}` depending on whether the Rust
747 /// toolchain supports panicking in `const fn`.
748 macro_rules! const_unreachable {
749     () => {{
750         #[cfg(zerocopy_panic_in_const_and_vec_try_reserve_1_57_0)]
751         unreachable!();
752 
753         #[cfg(not(zerocopy_panic_in_const_and_vec_try_reserve_1_57_0))]
754         loop {}
755     }};
756 }
757 
758 /// Asserts at compile time that `$condition` is true for `Self` or the given
759 /// `$tyvar`s. Unlike `const_assert`, this is *strictly* a compile-time check;
760 /// it cannot be evaluated in a runtime context. The condition is checked after
761 /// monomorphization and, upon failure, emits a compile error.
762 macro_rules! static_assert {
763     (Self $(: $(? $optbound:ident $(+)?)* $($bound:ident $(+)?)* )? => $condition:expr $(, $args:tt)*) => {{
764         trait StaticAssert {
765             const ASSERT: bool;
766         }
767 
768         impl<T $(: $(? $optbound +)* $($bound +)*)?> StaticAssert for T {
769             const ASSERT: bool = {
770                 const_assert!($condition $(, $args)*);
771                 $condition
772             };
773         }
774 
775         const_assert!(<Self as StaticAssert>::ASSERT);
776     }};
777     ($($tyvar:ident $(: $(? $optbound:ident $(+)?)* $($bound:ident $(+)?)* )?),* => $condition:expr $(, $args:tt)*) => {{
778         trait StaticAssert {
779             const ASSERT: bool;
780         }
781 
782         impl<$($tyvar $(: $(? $optbound +)* $($bound +)*)?,)*> StaticAssert for ($($tyvar,)*) {
783             const ASSERT: bool = {
784                 const_assert!($condition $(, $args)*);
785                 $condition
786             };
787         }
788 
789         const_assert!(<($($tyvar,)*) as StaticAssert>::ASSERT);
790     }};
791 }
792 
793 /// Assert at compile time that `tyvar` does not have a zero-sized DST
794 /// component.
795 macro_rules! static_assert_dst_is_not_zst {
796     ($tyvar:ident) => {{
797         use crate::KnownLayout;
798         static_assert!($tyvar: ?Sized + KnownLayout => {
799             let dst_is_zst = match $tyvar::LAYOUT.size_info {
800                 crate::SizeInfo::Sized { .. } => false,
801                 crate::SizeInfo::SliceDst(TrailingSliceLayout { elem_size, .. }) => {
802                     elem_size == 0
803                 }
804             };
805             !dst_is_zst
806         }, "cannot call this method on a dynamically-sized type whose trailing slice element is zero-sized");
807     }}
808 }
809