| 1 | |
| 2 | |
| 3 | |
| 4 | |
| 5 | |
| 6 | |
| 7 | |
| 8 | |
| 9 | |
| 10 |
|
| 11 | |
| 12 | |
| 13 | |
| 14 | |
| 15 | |
| 16 | |
| 17 | |
| 18 | |
| 19 | |
| 20 | |
| 21 | |
| 22 | |
| 23 | |
| 24 | macro_rules! unsafe_impl {
|
| 25 | |
| 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 | |
| 44 | |
| 45 | |
| 46 | |
| 47 | |
| 48 | |
| 49 | |
| 50 | |
| 51 | |
| 52 | |
| 53 | |
| 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 | |
| 67 | |
| 68 | |
| 69 | |
| 70 | |
| 71 | |
| 72 | |
| 73 | |
| 74 | |
| 75 | |
| 76 | |
| 77 | |
| 78 | |
| 79 | |
| 80 | |
| 81 | |
| 82 | |
| 83 | |
| 84 | |
| 85 | |
| 86 | |
| 87 | |
| 88 | |
| 89 | |
| 90 | |
| 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 | |
| 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 | |
| 170 | |
| 171 | |
| 172 | |
| 173 | |
| 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 | |
| 185 | |
| 186 | |
| 187 | |
| 188 | |
| 189 | |
| 190 | |
| 191 | |
| 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 | |
| 237 | |
| 238 | |
| 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 | |
| 248 | };
|
| 249 | }
|
| 250 |
|
| 251 | |
| 252 | |
| 253 | |
| 254 | |
| 255 | |
| 256 | |
| 257 | |
| 258 | |
| 259 | |
| 260 | |
| 261 | |
| 262 | |
| 263 | |
| 264 | |
| 265 | |
| 266 | |
| 267 | |
| 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 | |
| 310 | |
| 311 | macro_rules! opt_unsafe_extern_c_fn {
|
| 312 | ($($args:ident),* -> $ret:ident) => { Option<unsafe extern "C" fn($($args),*) -> $ret> };
|
| 313 | }
|
| 314 |
|
| 315 | |
| 316 | |
| 317 | macro_rules! opt_fn {
|
| 318 | ($($args:ident),* -> $ret:ident) => { Option<fn($($args),*) -> $ret> };
|
| 319 | }
|
| 320 |
|
| 321 | |
| 322 | |
| 323 | macro_rules! opt_unsafe_fn {
|
| 324 | ($($args:ident),* -> $ret:ident) => { Option<unsafe fn($($args),*) -> $ret> };
|
| 325 | }
|
| 326 |
|
| 327 | |
| 328 | |
| 329 | #[allow(rustdoc::private_intra_doc_links)]
|
| 330 | |
| 331 | |
| 332 | |
| 333 | |
| 334 | |
| 335 | |
| 336 | |
| 337 | |
| 338 | |
| 339 | |
| 340 | |
| 341 | |
| 342 | |
| 343 | |
| 344 | |
| 345 | |
| 346 | |
| 347 | |
| 348 | |
| 349 | |
| 350 | |
| 351 | |
| 352 | |
| 353 | |
| 354 | |
| 355 | |
| 356 | |
| 357 | |
| 358 | |
| 359 | |
| 360 | |
| 361 | |
| 362 | |
| 363 | |
| 364 | |
| 365 | |
| 366 | |
| 367 | |
| 368 | |
| 369 | |
| 370 | |
| 371 | |
| 372 | |
| 373 | |
| 374 | |
| 375 | |
| 376 | |
| 377 | |
| 378 | |
| 379 | #[cfg_attr(__ZEROCOPY_INTERNAL_USE_ONLY_DEV_MODE, macro_export)] |
| 380 | #[doc(hidden)]
|
| 381 | macro_rules! impl_or_verify {
|
| 382 | |
| 383 | |
| 384 | |
| 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 | |
| 417 | |
| 418 | #[allow(dead_code)]
|
| 419 | trait Subtrait: $trait {}
|
| 420 | $impl_block
|
| 421 | };
|
| 422 | };
|
| 423 | }
|
| 424 |
|
| 425 | |
| 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 | |
| 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 | |
| 449 | |
| 450 | |
| 451 | |
| 452 | |
| 453 | |
| 454 | |
| 455 | |
| 456 | |
| 457 | type MaybeUninit = core::mem::MaybeUninit<Self>;
|
| 458 |
|
| 459 | const LAYOUT: crate::DstLayout = crate::DstLayout::for_type::<$ty>();
|
| 460 |
|
| 461 | |
| 462 | |
| 463 | |
| 464 | |
| 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 | |
| 479 | |
| 480 | |
| 481 | |
| 482 | |
| 483 | |
| 484 | |
| 485 | |
| 486 | |
| 487 | |
| 488 | |
| 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 | |
| 538 | |
| 539 | |
| 540 | #[cfg(test)]
|
| 541 | static_assertions::const_assert_eq!(core::mem::align_of::<$tys>(), 1);
|
| 542 | )*
|
| 543 | };
|
| 544 | }
|
| 545 |
|
| 546 | |
| 547 | |
| 548 | |
| 549 | macro_rules! maybe_const_trait_bounded_fn {
|
| 550 | |
| 551 | |
| 552 | |
| 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 | |
| 563 | |
| 564 | |
| 565 | |
| 566 | |
| 567 | |
| 568 | macro_rules! const_panic {
|
| 569 | (@non_panic $($_arg:tt)+) => {{
|
| 570 | |
| 571 | |
| 572 | let panic: [_; 0] = [];
|
| 573 | |
| 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 | |
| 586 | |
| 587 | |
| 588 | |
| 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 | |
| 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 | |
| 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 | |
| 683 | |
| 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 | |
| 700 | |
| 701 | |
| 702 | |
| 703 | |
| 704 | |
| 705 | |
| 706 | |
| 707 | #[macro_export]
|
| 708 | #[doc(hidden)]
|
| 709 | macro_rules! define_cast {
|
| 710 | |
| 711 | |
| 712 | |
| 713 | |
| 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 | |
| 851 | |
| 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 | |
| 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 | |
| 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 | |
| 913 | #[doc = include_str!(concat!("../benches/formats/", $format, ".rs"))]
|
| 914 | |
| 915 | ],
|
| 916 | [
|
| 917 | @index 2
|
| 918 | @title "Benchmark"
|
| 919 | |
| 920 | #[doc = include_str!(concat!("../benches/", $bench, ".rs"))]
|
| 921 | |
| 922 | ],
|
| 923 | [
|
| 924 | open
|
| 925 | @index 3
|
| 926 | @title "Assembly"
|
| 927 | |
| 928 | #[doc = include_str!(concat!("../benches/", $bench, ".x86-64"))]
|
| 929 | |
| 930 | ],
|
| 931 | [
|
| 932 | @index 4
|
| 933 | @title "Machine Code Analysis"
|
| 934 | |
| 935 | #[doc = include_str!(concat!("../benches/", $bench, ".x86-64.mca"))]
|
| 936 | |
| 937 | ]
|
| 938 | )
|
| 939 | }
|
| 940 | }
|
| 941 |
|
| 942 | |
| 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 | |
| 973 | #[allow(unused)]
|
| 974 | macro_rules! codegen_preamble {
|
| 975 | () => {
|
| 976 | docstring!(
|
| 977 | |
| 978 | |
| 979 | |
| 980 | |
| 981 | |
| 982 | |
| 983 | )
|
| 984 | }
|
| 985 | }
|
| 986 |
|
| 987 | |
| 988 | |
| 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 | |
| 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 | |
| 1037 | |
| 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 | }
|