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