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`. 23 macro_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. 173 macro_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 /// ``` 274 macro_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`. 310 macro_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`. 316 macro_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`. 322 macro_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`. 328 macro_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)] 386 macro_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. 431 macro_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`). 494 macro_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. 539 macro_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. 554 macro_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. 573 macro_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. 594 macro_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!`. 620 macro_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`. 641 macro_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. 655 macro_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. 689 macro_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)] 714 macro_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). 746 macro_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 810 macro_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)] 845 pub(crate) const unsafe fn __unsafe() {} 846 847 /// Extracts the contents of doc comments. 848 #[allow(unused)] 849 macro_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)] 858 macro_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)] 882 macro_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)] 909 macro_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)] 949 macro_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)] 979 macro_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))] 996 macro_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)] 1023 macro_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 } 1073