diff --git a/build.rs b/build.rs index 141a74e74c..59688ac006 100644 --- a/build.rs +++ b/build.rs @@ -83,6 +83,7 @@ fn main() { println!( "cargo:rustc-check-cfg=cfg(__ZEROCOPY_INTERNAL_USE_ONLY_NIGHTLY_FEATURES_IN_TESTS)" ); + println!("cargo:rustc-check-cfg=cfg(zerocopy_unstable)"); println!("cargo:rustc-check-cfg=cfg(coverage_nightly)"); } diff --git a/src/impls.rs b/src/impls.rs index 05a198f463..a59cc2c5ef 100644 --- a/src/impls.rs +++ b/src/impls.rs @@ -7,6 +7,8 @@ // This file may not be copied, modified, or distributed except according to // those terms. +use core::mem::MaybeUninit as CoreMaybeUninit; + use super::*; safety_comment! { @@ -630,14 +632,14 @@ safety_comment! { /// SAFETY: /// `TryFromBytes` (with no validator), `FromZeros`, `FromBytes`: /// `MaybeUninit` has no restrictions on its contents. - unsafe_impl!(T => TryFromBytes for MaybeUninit); - unsafe_impl!(T => FromZeros for MaybeUninit); - unsafe_impl!(T => FromBytes for MaybeUninit); + unsafe_impl!(T => TryFromBytes for CoreMaybeUninit); + unsafe_impl!(T => FromZeros for CoreMaybeUninit); + unsafe_impl!(T => FromBytes for CoreMaybeUninit); } -impl_for_transparent_wrapper!(T: Immutable => Immutable for MaybeUninit); -impl_for_transparent_wrapper!(T: Unaligned => Unaligned for MaybeUninit); -assert_unaligned!(MaybeUninit<()>, MaybeUninit); +impl_for_transparent_wrapper!(T: Immutable => Immutable for CoreMaybeUninit); +impl_for_transparent_wrapper!(T: Unaligned => Unaligned for CoreMaybeUninit); +assert_unaligned!(CoreMaybeUninit<()>, CoreMaybeUninit); impl_for_transparent_wrapper!(T: ?Sized + Immutable => Immutable for ManuallyDrop); impl_for_transparent_wrapper!(T: ?Sized + TryFromBytes => TryFromBytes for ManuallyDrop); @@ -1254,8 +1256,8 @@ mod tests { ManuallyDrop>, ManuallyDrop<[UnsafeCell]>, ManuallyDrop<[UnsafeCell]>, - MaybeUninit, - MaybeUninit>, + CoreMaybeUninit, + CoreMaybeUninit>, Wrapping> ); @@ -1297,9 +1299,9 @@ mod tests { Option, Option, Option, - MaybeUninit, - MaybeUninit, - MaybeUninit>, + CoreMaybeUninit, + CoreMaybeUninit, + CoreMaybeUninit>, ManuallyDrop>, ManuallyDrop<[UnsafeCell]>, ManuallyDrop<[UnsafeCell]>, @@ -1761,9 +1763,9 @@ mod tests { assert_impls!(ManuallyDrop<[UnsafeCell]>: KnownLayout, TryFromBytes, FromZeros, FromBytes, IntoBytes, Unaligned, !Immutable); assert_impls!(ManuallyDrop<[UnsafeCell]>: KnownLayout, TryFromBytes, FromZeros, IntoBytes, Unaligned, !Immutable, !FromBytes); - assert_impls!(MaybeUninit: KnownLayout, Immutable, TryFromBytes, FromZeros, FromBytes, Unaligned, !IntoBytes); - assert_impls!(MaybeUninit: KnownLayout, TryFromBytes, FromZeros, FromBytes, !Immutable, !IntoBytes, !Unaligned); - assert_impls!(MaybeUninit>: KnownLayout, TryFromBytes, FromZeros, FromBytes, Unaligned, !Immutable, !IntoBytes); + assert_impls!(CoreMaybeUninit: KnownLayout, Immutable, TryFromBytes, FromZeros, FromBytes, Unaligned, !IntoBytes); + assert_impls!(CoreMaybeUninit: KnownLayout, TryFromBytes, FromZeros, FromBytes, !Immutable, !IntoBytes, !Unaligned); + assert_impls!(CoreMaybeUninit>: KnownLayout, TryFromBytes, FromZeros, FromBytes, Unaligned, !Immutable, !IntoBytes); assert_impls!(Wrapping: KnownLayout, Immutable, TryFromBytes, FromZeros, FromBytes, IntoBytes, Unaligned); // This test is important because it allows us to test our hand-rolled diff --git a/src/lib.rs b/src/lib.rs index 296836425a..9701589603 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -349,7 +349,7 @@ use core::{ fmt::{self, Debug, Display, Formatter}, hash::Hasher, marker::PhantomData, - mem::{self, ManuallyDrop, MaybeUninit}, + mem::{self, ManuallyDrop, MaybeUninit as CoreMaybeUninit}, num::{ NonZeroI128, NonZeroI16, NonZeroI32, NonZeroI64, NonZeroI8, NonZeroIsize, NonZeroU128, NonZeroU16, NonZeroU32, NonZeroU64, NonZeroU8, NonZeroUsize, Wrapping, @@ -724,6 +724,23 @@ pub unsafe trait KnownLayout { /// This is `()` for sized types and `usize` for slice DSTs. type PointerMetadata: PointerMetadata; + /// A maybe-uninitialized analog of `Self` + /// + /// # Safety + /// + /// Users may assume that: + /// - `Self` and `Self::MaybeUninit` have the same: + /// - Fixed prefix size + /// - Alignment + /// - (For DSTs) trailing slice element size + /// - It is valid to perform an `as` cast from `*mut Self` to `*mut + /// Self::MaybeUninit`, and this operation preserves referent size (ie, + /// `size_of_val_raw`). + /// - All bytes of `Self::MaybeUninit` may be uninitialized. + #[cfg(zerocopy_unstable)] + #[doc(hidden)] + type MaybeUninit: ?Sized + KnownLayout; + /// The layout of `Self`. /// /// # Safety @@ -856,6 +873,17 @@ unsafe impl KnownLayout for [T] { type PointerMetadata = usize; + // SAFETY: `CoreMaybeUninit` has the same size and alignment as `T`. + // Consequently, `[CoreMaybeUninit]` has the same size and alignment as + // `[T]`, becuase `CoreMaybeUninit` has the same size and alignment as + // `T` [1]. + // + // [1] Per https://doc.rust-lang.org/1.81.0/std/mem/union.MaybeUninit.html#layout-1: + // + // `MaybeUninit` is guaranteed to have the same size, alignment, and ABI as + // `T` + type MaybeUninit = [CoreMaybeUninit]; + const LAYOUT: DstLayout = DstLayout::for_slice::(); // SAFETY: `.cast` preserves address and provenance. The returned pointer @@ -908,7 +936,7 @@ impl_known_layout!( T => Option, T: ?Sized => PhantomData, T => Wrapping, - T => MaybeUninit, + T => CoreMaybeUninit, T: ?Sized => *const T, T: ?Sized => *mut T ); @@ -941,6 +969,19 @@ safety_comment! { unsafe_impl_known_layout!(T: ?Sized + KnownLayout => #[repr(T)] UnsafeCell); } +safety_comment! { + /// SAFETY: + /// - By invariant on `KnownLayout::MaybeUninit`, `T` and `T::MaybeUninit` + /// have the same: + /// - Fixed prefix size + /// - Alignment + /// - (For DSTs) trailing slice element size + /// - By invariant on `KnownLayout`, it is valid to perform an `as` cast + /// from `*mut T` and `*mut T::MaybeUninit`, and this operation preserves + /// referent size (ie, `size_of_val_raw`). + unsafe_impl_known_layout!(T: ?Sized + KnownLayout => #[repr(T::MaybeUninit)] MaybeUninit); +} + /// Analyzes whether a type is [`FromZeros`]. /// /// This derive analyzes, at compile time, whether the annotated type satisfies @@ -2539,7 +2580,7 @@ pub unsafe trait TryFromBytes { where Self: Sized, { - let candidate = match MaybeUninit::::read_from_bytes(source) { + let candidate = match CoreMaybeUninit::::read_from_bytes(source) { Ok(candidate) => candidate, Err(e) => { return Err(TryReadError::Size(e.with_dst())); @@ -2600,7 +2641,7 @@ pub unsafe trait TryFromBytes { where Self: Sized, { - let (candidate, suffix) = match MaybeUninit::::read_from_prefix(source) { + let (candidate, suffix) = match CoreMaybeUninit::::read_from_prefix(source) { Ok(candidate) => candidate, Err(e) => { return Err(TryReadError::Size(e.with_dst())); @@ -2662,7 +2703,7 @@ pub unsafe trait TryFromBytes { where Self: Sized, { - let (prefix, candidate) = match MaybeUninit::::read_from_suffix(source) { + let (prefix, candidate) = match CoreMaybeUninit::::read_from_suffix(source) { Ok(candidate) => candidate, Err(e) => { return Err(TryReadError::Size(e.with_dst())); @@ -2735,7 +2776,7 @@ fn swap((t, u): (T, U)) -> (U, T) { #[inline(always)] unsafe fn try_read_from( source: S, - mut candidate: MaybeUninit, + mut candidate: CoreMaybeUninit, ) -> Result> { // We use `from_mut` despite not mutating via `c_ptr` so that we don't need // to add a `T: Immutable` bound. diff --git a/src/util/macros.rs b/src/util/macros.rs index da2c37798d..03805ada25 100644 --- a/src/util/macros.rs +++ b/src/util/macros.rs @@ -530,6 +530,8 @@ macro_rules! impl_known_layout { type PointerMetadata = (); + type MaybeUninit = core::mem::MaybeUninit; + const LAYOUT: crate::DstLayout = crate::DstLayout::for_type::<$ty>(); // SAFETY: `.cast` preserves address and provenance. @@ -572,6 +574,7 @@ macro_rules! unsafe_impl_known_layout { fn only_derive_is_allowed_to_implement_this_trait() {} type PointerMetadata = <$repr as KnownLayout>::PointerMetadata; + type MaybeUninit = <$repr as KnownLayout>::MaybeUninit; const LAYOUT: DstLayout = <$repr as KnownLayout>::LAYOUT; diff --git a/src/util/mod.rs b/src/util/mod.rs index a05700cf02..0f37050cb2 100644 --- a/src/util/mod.rs +++ b/src/util/mod.rs @@ -683,6 +683,23 @@ pub(crate) unsafe fn copy_unchecked(src: &[u8], dst: &mut [u8]) { }; } +/// Unsafely transmutes the given `src` into a type `Dst`. +/// +/// # Safety +/// +/// The value `src` must be a bit-valid instance of `Dst`. +#[inline(always)] +pub(crate) const unsafe fn transmute_unchecked(src: Src) -> Dst { + static_assert!(Src, Dst => core::mem::size_of::() == core::mem::size_of::()); + #[repr(C)] + union Transmute { + src: ManuallyDrop, + dst: ManuallyDrop, + } + // SAFETY: The caller promises that `src` is a bit-valid instance of `Dst`. + unsafe { ManuallyDrop::into_inner(Transmute { src: ManuallyDrop::new(src) }.dst) } +} + /// Since we support multiple versions of Rust, there are often features which /// have been stabilized in the most recent stable release which do not yet /// exist (stably) on our MSRV. This module provides polyfills for those diff --git a/src/wrappers.rs b/src/wrappers.rs index 0637d76025..f819d6ac52 100644 --- a/src/wrappers.rs +++ b/src/wrappers.rs @@ -6,7 +6,7 @@ // This file may not be copied, modified, or distributed except according to // those terms. -use core::hash::Hash; +use core::{fmt, hash::Hash}; use super::*; @@ -464,6 +464,191 @@ impl Display for Unalign { } } +/// A wrapper type to construct uninitialized instances of `T`. +/// +/// `MaybeUninit` is identical to the [standard library +/// `MaybeUninit`][core-maybe-uninit] type except that it supports unsized +/// types. +/// +/// # Layout +/// +/// The same layout guarantees and caveats apply to `MaybeUninit` as apply to +/// the [standard library `MaybeUninit`][core-maybe-uninit] with one exception: +/// for `T: !Sized`, there is no single value for `T`'s size. Instead, for such +/// types, the following are guaranteed: +/// - Every [valid size][valid-size] for `T` is a valid size for +/// `MaybeUninit` and vice versa +/// - Given `t: *const T` and `m: *const MaybeUninit` with identical fat +/// pointer metadata, `t` and `m` address the same number of bytes (and +/// likewise for `*mut`) +/// +/// [core-maybe-uninit]: core::mem::MaybeUninit +/// [valid-size]: crate::KnownLayout#what-is-a-valid-size +#[repr(transparent)] +#[cfg(zerocopy_unstable)] +pub struct MaybeUninit(T::MaybeUninit); + +#[cfg(zerocopy_unstable)] +impl MaybeUninit { + /// Constructs a `MaybeUninit` initialized with the given value. + #[inline(always)] + pub fn new(val: T) -> Self + where + T: Sized + KnownLayout, + Self: Sized, + { + // SAFETY: It is valid to transmute `val` to `MaybeUninit` because it + // is both valid to transmute `val` to `T::MaybeUninit`, and it is valid + // to transmute from `T::MaybeUninit` to `MaybeUninit`. + // + // First, it is valid to transmute `val` to `T::MaybeUninit` because, by + // invariant on `T::MaybeUninit`: + // - `T` and `T::MaybeUninit` have the same size. + // - values of `T` are valid values of `T::MaybeUninit` + // + // Second, it is additionally valid to transmute from `T::MaybeUninit` + // to `MaybeUninit`, because `MaybeUninit` is a + // `repr(transparent)` wrapper around `T::MaybeUninit`. + // + // These two transmutes are collapsed into one so we don't need to add a + // `T::MaybeUninit: Sized` bound to this function's `where` clause. + unsafe { crate::util::transmute_unchecked(val) } + } + + /// Constructs an uninitialized `MaybeUninit`. + #[must_use] + #[inline(always)] + pub fn uninit() -> Self + where + T: Sized + KnownLayout, + Self: Sized, + { + let uninit = CoreMaybeUninit::::uninit(); + // SAFETY: It is valid to transmute `CoreMaybeUninit` to + // `MaybeUninit` as both have the same size (i.e., that of `T`) and + // bit validity (i.e., admitting uninitialized bytes). + unsafe { crate::util::transmute_unchecked(uninit) } + } + + /// Creates a `Box>`. + /// + /// This function is useful for allocating large, uninit values on the heap, + /// without ever creating a temporary instance of `Self` on the stack. + /// + /// # Errors + /// + /// Returns an error on allocation failure. Allocation failure is guaranteed + /// never to cause a panic or an abort. + #[cfg(feature = "alloc")] + #[inline] + pub fn new_boxed_uninit(meta: T::PointerMetadata) -> Result, AllocError> { + let align = Self::LAYOUT.align.get(); + let size = match meta.size_for_metadata(Self::LAYOUT) { + Some(size) => size, + None => return Err(AllocError), + }; + // On stable Rust versions <= 1.64.0, `Layout::from_size_align` has a + // bug in which sufficiently-large allocations (those which, when + // rounded up to the alignment, overflow `isize`) are not rejected, + // which can cause undefined behavior. See #64 for details. + // + // TODO(#67): Once our MSRV is > 1.64.0, remove this assertion. + #[allow(clippy::as_conversions)] + let max_alloc = (isize::MAX as usize).saturating_sub(align); + if size > max_alloc { + return Err(AllocError); + } + + // TODO(https://github.com/rust-lang/rust/issues/55724): Use + // `Layout::repeat` once it's stabilized. + let layout = Layout::from_size_align(size, align).or(Err(AllocError))?; + + let ptr = if layout.size() != 0 { + // TODO(#429): Add a "SAFETY" comment and remove this `allow`. + #[allow(clippy::undocumented_unsafe_blocks)] + let ptr = unsafe { alloc::alloc::alloc(layout) }; + match NonNull::new(ptr) { + Some(ptr) => ptr, + None => return Err(AllocError), + } + } else { + let align = Self::LAYOUT.align.get(); + // We use `transmute` instead of an `as` cast since Miri (with + // strict provenance enabled) notices and complains that an `as` + // cast creates a pointer with no provenance. Miri isn't smart + // enough to realize that we're only executing this branch when + // we're constructing a zero-sized `Box`, which doesn't require + // provenance. + // + // SAFETY: any initialized bit sequence is a bit-valid `*mut u8`. + // All bits of a `usize` are initialized. + #[allow(clippy::useless_transmute)] + let dangling = unsafe { mem::transmute::(align) }; + // SAFETY: `dangling` is constructed from `Self::LAYOUT.align`, + // which is a `NonZeroUsize`, which is guaranteed to be non-zero. + // + // `Box<[T]>` does not allocate when `T` is zero-sized or when `len` + // is zero, but it does require a non-null dangling pointer for its + // allocation. + // + // TODO(https://github.com/rust-lang/rust/issues/95228): Use + // `std::ptr::without_provenance` once it's stable. That may + // optimize better. As written, Rust may assume that this consumes + // "exposed" provenance, and thus Rust may have to assume that this + // may consume provenance from any pointer whose provenance has been + // exposed. + #[allow(fuzzy_provenance_casts)] + unsafe { + NonNull::new_unchecked(dangling) + } + }; + + let ptr = Self::raw_from_ptr_len(ptr, meta); + + // TODO(#429): Add a "SAFETY" comment and remove this `allow`. Make sure + // to include a justification that `ptr.as_ptr()` is validly-aligned in + // the ZST case (in which we manually construct a dangling pointer). + #[allow(clippy::undocumented_unsafe_blocks)] + Ok(unsafe { Box::from_raw(ptr.as_ptr()) }) + } + + /// TODO + #[inline(always)] + pub const fn as_ptr(&self) -> *const T { + todo!() + } + + /// TODO + #[inline(always)] + pub const fn as_mut_ptr(&self) -> *const T { + todo!() + } + + /// Extracts the value from the `MaybeUninit`` container. + /// + /// # Safety + /// + /// The caller must ensure that `self` is in an initialized state. Depending + /// on subsequent use, it may also need to be in a valid state. + #[inline(always)] + pub const unsafe fn assume_init(self) -> T + where + T: Sized + KnownLayout, + Self: Sized, + { + // SAFETY: The caller guarantees that `self` is in an initialized state. + unsafe { crate::util::transmute_unchecked(self) } + } +} + +#[cfg(zerocopy_unstable)] +impl fmt::Debug for MaybeUninit { + #[inline] + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.pad(core::any::type_name::()) + } +} + #[cfg(test)] mod tests { use core::panic::AssertUnwindSafe; diff --git a/tools/cargo-zerocopy/src/main.rs b/tools/cargo-zerocopy/src/main.rs index ec179b54f3..e5ad58cfac 100644 --- a/tools/cargo-zerocopy/src/main.rs +++ b/tools/cargo-zerocopy/src/main.rs @@ -166,9 +166,9 @@ fn install_toolchain_or_exit(versions: &Versions, name: &str) -> Result<(), Erro fn get_rustflags(name: &str) -> &'static str { // See #1792 for context on zerocopy_derive_union_into_bytes. if name == "nightly" { - "--cfg __ZEROCOPY_INTERNAL_USE_ONLY_NIGHTLY_FEATURES_IN_TESTS --cfg zerocopy_derive_union_into_bytes " + "--cfg __ZEROCOPY_INTERNAL_USE_ONLY_NIGHTLY_FEATURES_IN_TESTS --cfg zerocopy_derive_union_into_bytes --cfg zerocopy_unstable " } else { - "--cfg zerocopy_derive_union_into_bytes " + "--cfg zerocopy_derive_union_into_bytes --cfg zerocopy_unstable " } } diff --git a/zerocopy-derive/src/lib.rs b/zerocopy-derive/src/lib.rs index 65414b51fa..3cba48064e 100644 --- a/zerocopy-derive/src/lib.rs +++ b/zerocopy-derive/src/lib.rs @@ -139,8 +139,10 @@ fn derive_known_layout_inner(ast: &DeriveInput, _top_level: Trait) -> Result Result { + let ident = &ty.ident; + quote!(#ident) + } + GenericParam::Lifetime(l) => { + let ident = &l.lifetime; + quote!(#ident) + } + GenericParam::Const(cnst) => { + let ident = &cnst.ident; + quote!({#ident}) + } + }); + + let inner_extras = { + let leading_fields_tys = leading_fields_tys.clone(); quote!( type PointerMetadata = <#trailing_field_ty as ::zerocopy::KnownLayout>::PointerMetadata; + type MaybeUninit = __ZerocopyKnownLayoutMaybeUninit<#(#param_idents,)*>; + // SAFETY: `LAYOUT` accurately describes the layout of `Self`. // The layout of `Self` is reflected using a sequence of // invocations of `DstLayout::{new_zst,extend,pad_to_align}`. @@ -238,8 +258,10 @@ fn derive_known_layout_inner(ast: &DeriveInput, _top_level: Trait) -> Result Self::PointerMetadata { <#trailing_field_ty>::pointer_to_metadata(ptr as *mut _) } - ), - ) + ) + }; + + (SelfBounds::None, inner_extras, Some(repr)) } else { // For enums, unions, and non-`repr(C)` structs, we require that // `Self` is sized, and as a result don't need to reason about the @@ -248,6 +270,8 @@ fn derive_known_layout_inner(ast: &DeriveInput, _top_level: Trait) -> Result; // SAFETY: `LAYOUT` is guaranteed to accurately describe the // layout of `Self`, because that is the documented safety @@ -270,6 +294,7 @@ fn derive_known_layout_inner(ast: &DeriveInput, _top_level: Trait) -> Result () {} ), + None, ) }; @@ -292,7 +317,8 @@ fn derive_known_layout_inner(ast: &DeriveInput, _top_level: Trait) -> Result { @@ -305,7 +331,8 @@ fn derive_known_layout_inner(ast: &DeriveInput, _top_level: Trait) -> Result { @@ -318,7 +345,8 @@ fn derive_known_layout_inner(ast: &DeriveInput, _top_level: Trait) -> Result TokenStream { SelfBounds::None, None, None, + None, ), Data::Enum(enm) => impl_block( ast, @@ -343,6 +372,7 @@ fn derive_no_cell_inner(ast: &DeriveInput, _top_level: Trait) -> TokenStream { SelfBounds::None, None, None, + None, ), Data::Union(unn) => impl_block( ast, @@ -352,6 +382,7 @@ fn derive_no_cell_inner(ast: &DeriveInput, _top_level: Trait) -> TokenStream { SelfBounds::None, None, None, + None, ), } } @@ -453,6 +484,7 @@ fn derive_try_from_bytes_struct( SelfBounds::None, None, Some(extras), + None, )) } @@ -511,6 +543,7 @@ fn derive_try_from_bytes_union( SelfBounds::None, None, Some(extras), + None, ) } @@ -547,6 +580,7 @@ fn derive_try_from_bytes_enum( SelfBounds::None, None, Some(extra), + None, )) } @@ -629,7 +663,16 @@ unsafe fn gen_trivial_is_bit_valid_unchecked() -> proc_macro2::TokenStream { /// A struct is `FromZeros` if: /// - all fields are `FromZeros` fn derive_from_zeros_struct(ast: &DeriveInput, strct: &DataStruct) -> TokenStream { - impl_block(ast, strct, Trait::FromZeros, FieldBounds::ALL_SELF, SelfBounds::None, None, None) + impl_block( + ast, + strct, + Trait::FromZeros, + FieldBounds::ALL_SELF, + SelfBounds::None, + None, + None, + None, + ) } /// Returns `Ok(index)` if variant `index` of the enum has a discriminant of @@ -765,6 +808,7 @@ fn derive_from_zeros_enum(ast: &DeriveInput, enm: &DataEnum) -> Result TokenStream { // compatibility with `derive(TryFromBytes)` on unions; not for soundness. let field_type_trait_bounds = FieldBounds::All(&[TraitBound::Slf, TraitBound::Other(Trait::Immutable)]); - impl_block(ast, unn, Trait::FromZeros, field_type_trait_bounds, SelfBounds::None, None, None) + impl_block( + ast, + unn, + Trait::FromZeros, + field_type_trait_bounds, + SelfBounds::None, + None, + None, + None, + ) } /// A struct is `FromBytes` if: /// - all fields are `FromBytes` fn derive_from_bytes_struct(ast: &DeriveInput, strct: &DataStruct) -> TokenStream { - impl_block(ast, strct, Trait::FromBytes, FieldBounds::ALL_SELF, SelfBounds::None, None, None) + impl_block( + ast, + strct, + Trait::FromBytes, + FieldBounds::ALL_SELF, + SelfBounds::None, + None, + None, + None, + ) } /// An enum is `FromBytes` if: @@ -813,7 +875,16 @@ fn derive_from_bytes_enum(ast: &DeriveInput, enm: &DataEnum) -> Result TokenStream { // compatibility with `derive(TryFromBytes)` on unions; not for soundness. let field_type_trait_bounds = FieldBounds::All(&[TraitBound::Slf, TraitBound::Other(Trait::Immutable)]); - impl_block(ast, unn, Trait::FromBytes, field_type_trait_bounds, SelfBounds::None, None, None) + impl_block( + ast, + unn, + Trait::FromBytes, + field_type_trait_bounds, + SelfBounds::None, + None, + None, + None, + ) } fn derive_into_bytes_struct(ast: &DeriveInput, strct: &DataStruct) -> Result { @@ -913,6 +993,7 @@ fn derive_into_bytes_struct(ast: &DeriveInput, strct: &DataStruct) -> Result Result Result Result Result( field_type_trait_bounds: FieldBounds, self_type_trait_bounds: SelfBounds, padding_check: Option, - extras: Option, + inner_extras: Option, + known_layout_maybe_uninit_struct_repr: Option, ) -> TokenStream { // In this documentation, we will refer to this hypothetical struct: // @@ -1335,18 +1429,45 @@ fn impl_block( } }); + let outer_extras = if let Some(repr) = known_layout_maybe_uninit_struct_repr { + // PANICS: TODO + let (trailing_field, leading_fields) = fields.split_last().unwrap(); + let (_name, trailing_field_ty) = trailing_field; + let leading_fields_tys = leading_fields.iter().map(|(_name, ty)| ty); + let params = params.clone(); + let bounds = bounds.clone(); + quote! { + #repr + #[doc(hidden)] + pub struct __ZerocopyKnownLayoutMaybeUninit<#(#params),*>( + #( + ::zerocopy::util::macro_util::core_reexport::mem::MaybeUninit<#leading_fields_tys>, + )* + <#trailing_field_ty as ::zerocopy::KnownLayout>::MaybeUninit + ) where #(#bounds,)*; + } + } else { + quote! {} + }; + quote! { - // TODO(#553): Add a test that generates a warning when - // `#[allow(deprecated)]` isn't present. - #[allow(deprecated)] - unsafe impl < #(#params),* > #trait_path for #type_ident < #(#param_idents),* > - where - #(#bounds,)* - { - fn only_derive_is_allowed_to_implement_this_trait() {} + // So that any items defined in `#outer_extras` don't conflict with + // existing names defined in this scope. + const _: () = { + // TODO(#553): Add a test that generates a warning when + // `#[allow(deprecated)]` isn't present. + #[allow(deprecated)] + unsafe impl < #(#params),* > #trait_path for #type_ident < #(#param_idents),* > + where + #(#bounds,)* + { + fn only_derive_is_allowed_to_implement_this_trait() {} - #extras - } + #inner_extras + } + + #outer_extras + }; } } diff --git a/zerocopy-derive/src/output_tests.rs b/zerocopy-derive/src/output_tests.rs index 32377e5ea3..dfe2981944 100644 --- a/zerocopy-derive/src/output_tests.rs +++ b/zerocopy-derive/src/output_tests.rs @@ -101,28 +101,32 @@ fn test_known_layout() { KnownLayout { struct Foo; } expands to { - #[allow(deprecated)] - unsafe impl ::zerocopy::KnownLayout for Foo - where - Self: ::zerocopy::util::macro_util::core_reexport::marker::Sized, - { - fn only_derive_is_allowed_to_implement_this_trait() {} + const _: () = { + #[allow(deprecated)] + unsafe impl ::zerocopy::KnownLayout for Foo + where + Self: ::zerocopy::util::macro_util::core_reexport::marker::Sized, + { + fn only_derive_is_allowed_to_implement_this_trait() {} - type PointerMetadata = (); + type PointerMetadata = (); - const LAYOUT: ::zerocopy::DstLayout = ::zerocopy::DstLayout::for_type::(); + type MaybeUninit = ::zerocopy::util::macro_util::core_reexport::mem::MaybeUninit; - #[inline(always)] - fn raw_from_ptr_len( - bytes: ::zerocopy::util::macro_util::core_reexport::ptr::NonNull, - _meta: (), - ) -> ::zerocopy::util::macro_util::core_reexport::ptr::NonNull { - bytes.cast::() - } + const LAYOUT: ::zerocopy::DstLayout = ::zerocopy::DstLayout::for_type::(); - #[inline(always)] - fn pointer_to_metadata(_ptr: *mut Self) -> () {} - } + #[inline(always)] + fn raw_from_ptr_len( + bytes: ::zerocopy::util::macro_util::core_reexport::ptr::NonNull, + _meta: (), + ) -> ::zerocopy::util::macro_util::core_reexport::ptr::NonNull { + bytes.cast::() + } + + #[inline(always)] + fn pointer_to_metadata(_ptr: *mut Self) -> () {} + } + }; } no_build } } @@ -133,10 +137,12 @@ fn test_immutable() { Immutable { struct Foo; } expands to { - #[allow(deprecated)] - unsafe impl ::zerocopy::Immutable for Foo { - fn only_derive_is_allowed_to_implement_this_trait() {} - } + const _: () = { + #[allow(deprecated)] + unsafe impl ::zerocopy::Immutable for Foo { + fn only_derive_is_allowed_to_implement_this_trait() {} + } + }; } no_build } } @@ -147,20 +153,22 @@ fn test_try_from_bytes() { TryFromBytes { struct Foo; } expands to { - #[allow(deprecated)] - unsafe impl ::zerocopy::TryFromBytes for Foo { - fn only_derive_is_allowed_to_implement_this_trait() {} + const _: () = { + #[allow(deprecated)] + unsafe impl ::zerocopy::TryFromBytes for Foo { + fn only_derive_is_allowed_to_implement_this_trait() {} - fn is_bit_valid<___ZerocopyAliasing>( - mut candidate: ::zerocopy::Maybe, - ) -> ::zerocopy::util::macro_util::core_reexport::primitive::bool - where - ___ZerocopyAliasing: ::zerocopy::pointer::invariant::Aliasing - + ::zerocopy::pointer::invariant::AtLeast<::zerocopy::pointer::invariant::Shared>, - { - true + fn is_bit_valid<___ZerocopyAliasing>( + mut candidate: ::zerocopy::Maybe, + ) -> ::zerocopy::util::macro_util::core_reexport::primitive::bool + where + ___ZerocopyAliasing: ::zerocopy::pointer::invariant::Aliasing + + ::zerocopy::pointer::invariant::AtLeast<::zerocopy::pointer::invariant::Shared>, + { + true + } } - } + }; } no_build } } @@ -171,25 +179,29 @@ fn test_from_zeros() { FromZeros { struct Foo; } expands to { - #[allow(deprecated)] - unsafe impl ::zerocopy::TryFromBytes for Foo { - fn only_derive_is_allowed_to_implement_this_trait() {} + const _: () = { + #[allow(deprecated)] + unsafe impl ::zerocopy::TryFromBytes for Foo { + fn only_derive_is_allowed_to_implement_this_trait() {} - fn is_bit_valid<___ZerocopyAliasing>( - mut candidate: ::zerocopy::Maybe, - ) -> ::zerocopy::util::macro_util::core_reexport::primitive::bool - where - ___ZerocopyAliasing: ::zerocopy::pointer::invariant::Aliasing - + ::zerocopy::pointer::invariant::AtLeast<::zerocopy::pointer::invariant::Shared>, - { - true + fn is_bit_valid<___ZerocopyAliasing>( + mut candidate: ::zerocopy::Maybe, + ) -> ::zerocopy::util::macro_util::core_reexport::primitive::bool + where + ___ZerocopyAliasing: ::zerocopy::pointer::invariant::Aliasing + + ::zerocopy::pointer::invariant::AtLeast<::zerocopy::pointer::invariant::Shared>, + { + true + } } - } + }; - #[allow(deprecated)] - unsafe impl ::zerocopy::FromZeros for Foo { - fn only_derive_is_allowed_to_implement_this_trait() {} - } + const _: () = { + #[allow(deprecated)] + unsafe impl ::zerocopy::FromZeros for Foo { + fn only_derive_is_allowed_to_implement_this_trait() {} + } + }; } no_build } } @@ -200,39 +212,45 @@ fn test_from_bytes_struct() { FromBytes { struct Foo; } expands to { - #[allow(deprecated)] - unsafe impl ::zerocopy::TryFromBytes for Foo { - fn only_derive_is_allowed_to_implement_this_trait() {} + const _: () = { + #[allow(deprecated)] + unsafe impl ::zerocopy::TryFromBytes for Foo { + fn only_derive_is_allowed_to_implement_this_trait() {} - fn is_bit_valid<___ZerocopyAliasing>( - _candidate: ::zerocopy::Maybe, - ) -> ::zerocopy::util::macro_util::core_reexport::primitive::bool - where - ___ZerocopyAliasing: ::zerocopy::pointer::invariant::Aliasing - + ::zerocopy::pointer::invariant::AtLeast<::zerocopy::pointer::invariant::Shared>, - { - if false { - fn assert_is_from_bytes() - where - T: ::zerocopy::FromBytes, - T: ?::zerocopy::util::macro_util::core_reexport::marker::Sized, - {} - assert_is_from_bytes::(); - } + fn is_bit_valid<___ZerocopyAliasing>( + _candidate: ::zerocopy::Maybe, + ) -> ::zerocopy::util::macro_util::core_reexport::primitive::bool + where + ___ZerocopyAliasing: ::zerocopy::pointer::invariant::Aliasing + + ::zerocopy::pointer::invariant::AtLeast<::zerocopy::pointer::invariant::Shared>, + { + if false { + fn assert_is_from_bytes() + where + T: ::zerocopy::FromBytes, + T: ?::zerocopy::util::macro_util::core_reexport::marker::Sized, + {} + assert_is_from_bytes::(); + } - true + true + } } - } + }; - #[allow(deprecated)] - unsafe impl ::zerocopy::FromZeros for Foo { - fn only_derive_is_allowed_to_implement_this_trait() {} - } + const _: () = { + #[allow(deprecated)] + unsafe impl ::zerocopy::FromZeros for Foo { + fn only_derive_is_allowed_to_implement_this_trait() {} + } + }; - #[allow(deprecated)] - unsafe impl ::zerocopy::FromBytes for Foo { - fn only_derive_is_allowed_to_implement_this_trait() {} - } + const _: () = { + #[allow(deprecated)] + unsafe impl ::zerocopy::FromBytes for Foo { + fn only_derive_is_allowed_to_implement_this_trait() {} + } + }; } no_build } } @@ -245,48 +263,54 @@ fn test_from_bytes_union() { a: u8, } } expands to { - #[allow(deprecated)] - unsafe impl ::zerocopy::TryFromBytes for Foo - where - u8: ::zerocopy::TryFromBytes + ::zerocopy::Immutable, - { - fn only_derive_is_allowed_to_implement_this_trait() {} - - fn is_bit_valid<___ZerocopyAliasing>( - _candidate: ::zerocopy::Maybe, - ) -> ::zerocopy::util::macro_util::core_reexport::primitive::bool + const _: () = { + #[allow(deprecated)] + unsafe impl ::zerocopy::TryFromBytes for Foo where - ___ZerocopyAliasing: ::zerocopy::pointer::invariant::Aliasing - + ::zerocopy::pointer::invariant::AtLeast<::zerocopy::pointer::invariant::Shared>, + u8: ::zerocopy::TryFromBytes + ::zerocopy::Immutable, { - if false { - fn assert_is_from_bytes() - where - T: ::zerocopy::FromBytes, - T: ?::zerocopy::util::macro_util::core_reexport::marker::Sized, - {} - assert_is_from_bytes::(); - } + fn only_derive_is_allowed_to_implement_this_trait() {} + + fn is_bit_valid<___ZerocopyAliasing>( + _candidate: ::zerocopy::Maybe, + ) -> ::zerocopy::util::macro_util::core_reexport::primitive::bool + where + ___ZerocopyAliasing: ::zerocopy::pointer::invariant::Aliasing + + ::zerocopy::pointer::invariant::AtLeast<::zerocopy::pointer::invariant::Shared>, + { + if false { + fn assert_is_from_bytes() + where + T: ::zerocopy::FromBytes, + T: ?::zerocopy::util::macro_util::core_reexport::marker::Sized, + {} + assert_is_from_bytes::(); + } - true + true + } } - } + }; - #[allow(deprecated)] - unsafe impl ::zerocopy::FromZeros for Foo - where - u8: ::zerocopy::FromZeros + ::zerocopy::Immutable, - { - fn only_derive_is_allowed_to_implement_this_trait() {} - } + const _: () = { + #[allow(deprecated)] + unsafe impl ::zerocopy::FromZeros for Foo + where + u8: ::zerocopy::FromZeros + ::zerocopy::Immutable, + { + fn only_derive_is_allowed_to_implement_this_trait() {} + } + }; - #[allow(deprecated)] - unsafe impl ::zerocopy::FromBytes for Foo - where - u8: ::zerocopy::FromBytes + ::zerocopy::Immutable, - { - fn only_derive_is_allowed_to_implement_this_trait() {} - } + const _: () = { + #[allow(deprecated)] + unsafe impl ::zerocopy::FromBytes for Foo + where + u8: ::zerocopy::FromBytes + ::zerocopy::Immutable, + { + fn only_derive_is_allowed_to_implement_this_trait() {} + } + }; } no_build } } @@ -298,10 +322,12 @@ fn test_into_bytes() { #[repr(C)] struct Foo; } expands to { - #[allow(deprecated)] - unsafe impl ::zerocopy::IntoBytes for Foo { - fn only_derive_is_allowed_to_implement_this_trait() {} - } + const _: () = { + #[allow(deprecated)] + unsafe impl ::zerocopy::IntoBytes for Foo { + fn only_derive_is_allowed_to_implement_this_trait() {} + } + }; } no_build } @@ -313,18 +339,20 @@ fn test_into_bytes() { b: u8, } } expands to { - #[allow(deprecated)] - unsafe impl ::zerocopy::IntoBytes for Foo - where - u8: ::zerocopy::IntoBytes, - u8: ::zerocopy::IntoBytes, - (): ::zerocopy::util::macro_util::PaddingFree< - Self, - { ::zerocopy::struct_has_padding!(Self, [u8, u8]) }, - >, - { - fn only_derive_is_allowed_to_implement_this_trait() {} - } + const _: () = { + #[allow(deprecated)] + unsafe impl ::zerocopy::IntoBytes for Foo + where + u8: ::zerocopy::IntoBytes, + u8: ::zerocopy::IntoBytes, + (): ::zerocopy::util::macro_util::PaddingFree< + Self, + { ::zerocopy::struct_has_padding!(Self, [u8, u8]) }, + >, + { + fn only_derive_is_allowed_to_implement_this_trait() {} + } + }; } no_build } } @@ -336,10 +364,12 @@ fn test_unaligned() { #[repr(C)] struct Foo; } expands to { - #[allow(deprecated)] - unsafe impl ::zerocopy::Unaligned for Foo { - fn only_derive_is_allowed_to_implement_this_trait() {} - } + const _: () = { + #[allow(deprecated)] + unsafe impl ::zerocopy::Unaligned for Foo { + fn only_derive_is_allowed_to_implement_this_trait() {} + } + }; } no_build } } @@ -358,285 +388,291 @@ fn test_try_from_bytes_enum() { TupleLike(bool, Y, PhantomData<&'a [(X, Y); N]>), } } expands to { - #[allow(deprecated)] - unsafe impl<'a: 'static, const N: usize, X, Y: Deref> ::zerocopy::TryFromBytes - for ComplexWithGenerics<'a, { N }, X, Y> - where - X: Deref, - u8: ::zerocopy::TryFromBytes, - X: ::zerocopy::TryFromBytes, - X::Target: ::zerocopy::TryFromBytes, - Y::Target: ::zerocopy::TryFromBytes, - [(X, Y); N]: ::zerocopy::TryFromBytes, - bool: ::zerocopy::TryFromBytes, - Y: ::zerocopy::TryFromBytes, - PhantomData<&'a [(X, Y); N]>: ::zerocopy::TryFromBytes, - { - fn only_derive_is_allowed_to_implement_this_trait() {} - fn is_bit_valid<___ZerocopyAliasing>( - mut candidate: ::zerocopy::Maybe<'_, Self, ___ZerocopyAliasing>, - ) -> ::zerocopy::util::macro_util::core_reexport::primitive::bool + const _: () = { + #[allow(deprecated)] + unsafe impl<'a: 'static, const N: usize, X, Y: Deref> ::zerocopy::TryFromBytes + for ComplexWithGenerics<'a, { N }, X, Y> where - ___ZerocopyAliasing: ::zerocopy::pointer::invariant::Aliasing - + ::zerocopy::pointer::invariant::AtLeast<::zerocopy::pointer::invariant::Shared>, + X: Deref, + u8: ::zerocopy::TryFromBytes, + X: ::zerocopy::TryFromBytes, + X::Target: ::zerocopy::TryFromBytes, + Y::Target: ::zerocopy::TryFromBytes, + [(X, Y); N]: ::zerocopy::TryFromBytes, + bool: ::zerocopy::TryFromBytes, + Y: ::zerocopy::TryFromBytes, + PhantomData<&'a [(X, Y); N]>: ::zerocopy::TryFromBytes, { - use ::zerocopy::util::macro_util::core_reexport; - #[repr(u8)] - #[allow(dead_code)] - enum ___ZerocopyTag { - UnitLike, - StructLike, - TupleLike, - } - type ___ZerocopyTagPrimitive = ::zerocopy::util::macro_util::SizeToTag< - { core_reexport::mem::size_of::<___ZerocopyTag>() }, - >; - #[allow(non_upper_case_globals)] - const ___ZEROCOPY_TAG_UnitLike: ___ZerocopyTagPrimitive = - ___ZerocopyTag::UnitLike as ___ZerocopyTagPrimitive; - #[allow(non_upper_case_globals)] - const ___ZEROCOPY_TAG_StructLike: ___ZerocopyTagPrimitive = - ___ZerocopyTag::StructLike as ___ZerocopyTagPrimitive; - #[allow(non_upper_case_globals)] - const ___ZEROCOPY_TAG_TupleLike: ___ZerocopyTagPrimitive = - ___ZerocopyTag::TupleLike as ___ZerocopyTagPrimitive; - type ___ZerocopyOuterTag = (); - type ___ZerocopyInnerTag = ___ZerocopyTag; - #[repr(C)] - #[allow(non_snake_case)] - struct ___ZerocopyVariantStruct_StructLike<'a: 'static, const N: usize, X, Y: Deref>( - core_reexport::mem::MaybeUninit<___ZerocopyInnerTag>, - u8, - X, - X::Target, - Y::Target, - [(X, Y); N], - core_reexport::marker::PhantomData>, - ) - where - X: Deref; - #[allow(deprecated)] - unsafe impl<'a: 'static, const N: usize, X, Y: Deref> ::zerocopy::TryFromBytes - for ___ZerocopyVariantStruct_StructLike<'a, { N }, X, Y> + fn only_derive_is_allowed_to_implement_this_trait() {} + fn is_bit_valid<___ZerocopyAliasing>( + mut candidate: ::zerocopy::Maybe<'_, Self, ___ZerocopyAliasing>, + ) -> ::zerocopy::util::macro_util::core_reexport::primitive::bool where - X: Deref, - core_reexport::mem::MaybeUninit<___ZerocopyInnerTag>: ::zerocopy::TryFromBytes, - u8: ::zerocopy::TryFromBytes, - X: ::zerocopy::TryFromBytes, - X::Target: ::zerocopy::TryFromBytes, - Y::Target: ::zerocopy::TryFromBytes, - [(X, Y); N]: ::zerocopy::TryFromBytes, - core_reexport::marker::PhantomData>: - ::zerocopy::TryFromBytes, + ___ZerocopyAliasing: ::zerocopy::pointer::invariant::Aliasing + + ::zerocopy::pointer::invariant::AtLeast<::zerocopy::pointer::invariant::Shared>, { - fn only_derive_is_allowed_to_implement_this_trait() {} - fn is_bit_valid<___ZerocopyAliasing>( - mut candidate: ::zerocopy::Maybe, - ) -> ::zerocopy::util::macro_util::core_reexport::primitive::bool + use ::zerocopy::util::macro_util::core_reexport; + #[repr(u8)] + #[allow(dead_code)] + enum ___ZerocopyTag { + UnitLike, + StructLike, + TupleLike, + } + type ___ZerocopyTagPrimitive = ::zerocopy::util::macro_util::SizeToTag< + { core_reexport::mem::size_of::<___ZerocopyTag>() }, + >; + #[allow(non_upper_case_globals)] + const ___ZEROCOPY_TAG_UnitLike: ___ZerocopyTagPrimitive = + ___ZerocopyTag::UnitLike as ___ZerocopyTagPrimitive; + #[allow(non_upper_case_globals)] + const ___ZEROCOPY_TAG_StructLike: ___ZerocopyTagPrimitive = + ___ZerocopyTag::StructLike as ___ZerocopyTagPrimitive; + #[allow(non_upper_case_globals)] + const ___ZEROCOPY_TAG_TupleLike: ___ZerocopyTagPrimitive = + ___ZerocopyTag::TupleLike as ___ZerocopyTagPrimitive; + type ___ZerocopyOuterTag = (); + type ___ZerocopyInnerTag = ___ZerocopyTag; + #[repr(C)] + #[allow(non_snake_case)] + struct ___ZerocopyVariantStruct_StructLike<'a: 'static, const N: usize, X, Y: Deref>( + core_reexport::mem::MaybeUninit<___ZerocopyInnerTag>, + u8, + X, + X::Target, + Y::Target, + [(X, Y); N], + core_reexport::marker::PhantomData>, + ) where - ___ZerocopyAliasing: ::zerocopy::pointer::invariant::Aliasing - + ::zerocopy::pointer::invariant::AtLeast<::zerocopy::pointer::invariant::Shared>, - { - true && { - let field_candidate = unsafe { - let project = |slf: *mut Self| { - ::zerocopy::util::macro_util::core_reexport::ptr::addr_of_mut!((*slf).0) - }; - candidate.reborrow().project(project) - }; - as ::zerocopy::TryFromBytes>::is_bit_valid(field_candidate) - } && { - let field_candidate = unsafe { - let project = |slf: *mut Self| { - ::zerocopy::util::macro_util::core_reexport::ptr::addr_of_mut!((*slf).1) - }; - candidate.reborrow().project(project) - }; - ::is_bit_valid(field_candidate) - } && { - let field_candidate = unsafe { - let project = |slf: *mut Self| { - ::zerocopy::util::macro_util::core_reexport::ptr::addr_of_mut!((*slf).2) - }; - candidate.reborrow().project(project) - }; - ::is_bit_valid(field_candidate) - } && { - let field_candidate = unsafe { - let project = |slf: *mut Self| { - ::zerocopy::util::macro_util::core_reexport::ptr::addr_of_mut!((*slf).3) - }; - candidate.reborrow().project(project) - }; - ::is_bit_valid(field_candidate) - } && { - let field_candidate = unsafe { - let project = |slf: *mut Self| { - ::zerocopy::util::macro_util::core_reexport::ptr::addr_of_mut!((*slf).4) - }; - candidate.reborrow().project(project) - }; - ::is_bit_valid(field_candidate) - } && { - let field_candidate = unsafe { - let project = |slf: *mut Self| { - ::zerocopy::util::macro_util::core_reexport::ptr::addr_of_mut!((*slf).5) - }; - candidate.reborrow().project(project) - }; - <[(X, Y); N] as ::zerocopy::TryFromBytes>::is_bit_valid(field_candidate) - } && { - let field_candidate = unsafe { - let project = |slf: *mut Self| { - ::zerocopy::util::macro_util::core_reexport::ptr::addr_of_mut!((*slf).6) - }; - candidate.reborrow().project(project) - }; - , - > as ::zerocopy::TryFromBytes>::is_bit_valid(field_candidate) + X: Deref; + const _: () = { + #[allow(deprecated)] + unsafe impl<'a: 'static, const N: usize, X, Y: Deref> ::zerocopy::TryFromBytes + for ___ZerocopyVariantStruct_StructLike<'a, { N }, X, Y> + where + X: Deref, + core_reexport::mem::MaybeUninit<___ZerocopyInnerTag>: ::zerocopy::TryFromBytes, + u8: ::zerocopy::TryFromBytes, + X: ::zerocopy::TryFromBytes, + X::Target: ::zerocopy::TryFromBytes, + Y::Target: ::zerocopy::TryFromBytes, + [(X, Y); N]: ::zerocopy::TryFromBytes, + core_reexport::marker::PhantomData>: + ::zerocopy::TryFromBytes, + { + fn only_derive_is_allowed_to_implement_this_trait() {} + fn is_bit_valid<___ZerocopyAliasing>( + mut candidate: ::zerocopy::Maybe, + ) -> ::zerocopy::util::macro_util::core_reexport::primitive::bool + where + ___ZerocopyAliasing: ::zerocopy::pointer::invariant::Aliasing + + ::zerocopy::pointer::invariant::AtLeast<::zerocopy::pointer::invariant::Shared>, + { + true && { + let field_candidate = unsafe { + let project = |slf: *mut Self| { + ::zerocopy::util::macro_util::core_reexport::ptr::addr_of_mut!((*slf).0) + }; + candidate.reborrow().project(project) + }; + as ::zerocopy::TryFromBytes>::is_bit_valid(field_candidate) + } && { + let field_candidate = unsafe { + let project = |slf: *mut Self| { + ::zerocopy::util::macro_util::core_reexport::ptr::addr_of_mut!((*slf).1) + }; + candidate.reborrow().project(project) + }; + ::is_bit_valid(field_candidate) + } && { + let field_candidate = unsafe { + let project = |slf: *mut Self| { + ::zerocopy::util::macro_util::core_reexport::ptr::addr_of_mut!((*slf).2) + }; + candidate.reborrow().project(project) + }; + ::is_bit_valid(field_candidate) + } && { + let field_candidate = unsafe { + let project = |slf: *mut Self| { + ::zerocopy::util::macro_util::core_reexport::ptr::addr_of_mut!((*slf).3) + }; + candidate.reborrow().project(project) + }; + ::is_bit_valid(field_candidate) + } && { + let field_candidate = unsafe { + let project = |slf: *mut Self| { + ::zerocopy::util::macro_util::core_reexport::ptr::addr_of_mut!((*slf).4) + }; + candidate.reborrow().project(project) + }; + ::is_bit_valid(field_candidate) + } && { + let field_candidate = unsafe { + let project = |slf: *mut Self| { + ::zerocopy::util::macro_util::core_reexport::ptr::addr_of_mut!((*slf).5) + }; + candidate.reborrow().project(project) + }; + <[(X, Y); N] as ::zerocopy::TryFromBytes>::is_bit_valid(field_candidate) + } && { + let field_candidate = unsafe { + let project = |slf: *mut Self| { + ::zerocopy::util::macro_util::core_reexport::ptr::addr_of_mut!((*slf).6) + }; + candidate.reborrow().project(project) + }; + , + > as ::zerocopy::TryFromBytes>::is_bit_valid(field_candidate) + } + } } - } - } - #[repr(C)] - #[allow(non_snake_case)] - struct ___ZerocopyVariantStruct_TupleLike<'a: 'static, const N: usize, X, Y: Deref>( - core_reexport::mem::MaybeUninit<___ZerocopyInnerTag>, - bool, - Y, - PhantomData<&'a [(X, Y); N]>, - core_reexport::marker::PhantomData>, - ) - where - X: Deref; - #[allow(deprecated)] - unsafe impl<'a: 'static, const N: usize, X, Y: Deref> ::zerocopy::TryFromBytes - for ___ZerocopyVariantStruct_TupleLike<'a, { N }, X, Y> - where - X: Deref, - core_reexport::mem::MaybeUninit<___ZerocopyInnerTag>: ::zerocopy::TryFromBytes, - bool: ::zerocopy::TryFromBytes, - Y: ::zerocopy::TryFromBytes, - PhantomData<&'a [(X, Y); N]>: ::zerocopy::TryFromBytes, - core_reexport::marker::PhantomData>: - ::zerocopy::TryFromBytes, - { - fn only_derive_is_allowed_to_implement_this_trait() {} - fn is_bit_valid<___ZerocopyAliasing>( - mut candidate: ::zerocopy::Maybe, - ) -> ::zerocopy::util::macro_util::core_reexport::primitive::bool + }; + #[repr(C)] + #[allow(non_snake_case)] + struct ___ZerocopyVariantStruct_TupleLike<'a: 'static, const N: usize, X, Y: Deref>( + core_reexport::mem::MaybeUninit<___ZerocopyInnerTag>, + bool, + Y, + PhantomData<&'a [(X, Y); N]>, + core_reexport::marker::PhantomData>, + ) where - ___ZerocopyAliasing: ::zerocopy::pointer::invariant::Aliasing - + ::zerocopy::pointer::invariant::AtLeast<::zerocopy::pointer::invariant::Shared>, - { - true && { - let field_candidate = unsafe { - let project = |slf: *mut Self| { - ::zerocopy::util::macro_util::core_reexport::ptr::addr_of_mut!((*slf).0) - }; - candidate.reborrow().project(project) - }; - as ::zerocopy::TryFromBytes>::is_bit_valid(field_candidate) - } && { - let field_candidate = unsafe { - let project = |slf: *mut Self| { - ::zerocopy::util::macro_util::core_reexport::ptr::addr_of_mut!((*slf).1) - }; - candidate.reborrow().project(project) - }; - ::is_bit_valid(field_candidate) - } && { - let field_candidate = unsafe { - let project = |slf: *mut Self| { - ::zerocopy::util::macro_util::core_reexport::ptr::addr_of_mut!((*slf).2) - }; - candidate.reborrow().project(project) - }; - ::is_bit_valid(field_candidate) - } && { - let field_candidate = unsafe { - let project = |slf: *mut Self| { - ::zerocopy::util::macro_util::core_reexport::ptr::addr_of_mut!((*slf).3) - }; - candidate.reborrow().project(project) - }; - as ::zerocopy::TryFromBytes>::is_bit_valid( - field_candidate, - ) - } && { - let field_candidate = unsafe { - let project = |slf: *mut Self| { - ::zerocopy::util::macro_util::core_reexport::ptr::addr_of_mut!((*slf).4) - }; - candidate.reborrow().project(project) - }; - , - > as ::zerocopy::TryFromBytes>::is_bit_valid(field_candidate) + X: Deref; + const _: () = { + #[allow(deprecated)] + unsafe impl<'a: 'static, const N: usize, X, Y: Deref> ::zerocopy::TryFromBytes + for ___ZerocopyVariantStruct_TupleLike<'a, { N }, X, Y> + where + X: Deref, + core_reexport::mem::MaybeUninit<___ZerocopyInnerTag>: ::zerocopy::TryFromBytes, + bool: ::zerocopy::TryFromBytes, + Y: ::zerocopy::TryFromBytes, + PhantomData<&'a [(X, Y); N]>: ::zerocopy::TryFromBytes, + core_reexport::marker::PhantomData>: + ::zerocopy::TryFromBytes, + { + fn only_derive_is_allowed_to_implement_this_trait() {} + fn is_bit_valid<___ZerocopyAliasing>( + mut candidate: ::zerocopy::Maybe, + ) -> ::zerocopy::util::macro_util::core_reexport::primitive::bool + where + ___ZerocopyAliasing: ::zerocopy::pointer::invariant::Aliasing + + ::zerocopy::pointer::invariant::AtLeast<::zerocopy::pointer::invariant::Shared>, + { + true && { + let field_candidate = unsafe { + let project = |slf: *mut Self| { + ::zerocopy::util::macro_util::core_reexport::ptr::addr_of_mut!((*slf).0) + }; + candidate.reborrow().project(project) + }; + as ::zerocopy::TryFromBytes>::is_bit_valid(field_candidate) + } && { + let field_candidate = unsafe { + let project = |slf: *mut Self| { + ::zerocopy::util::macro_util::core_reexport::ptr::addr_of_mut!((*slf).1) + }; + candidate.reborrow().project(project) + }; + ::is_bit_valid(field_candidate) + } && { + let field_candidate = unsafe { + let project = |slf: *mut Self| { + ::zerocopy::util::macro_util::core_reexport::ptr::addr_of_mut!((*slf).2) + }; + candidate.reborrow().project(project) + }; + ::is_bit_valid(field_candidate) + } && { + let field_candidate = unsafe { + let project = |slf: *mut Self| { + ::zerocopy::util::macro_util::core_reexport::ptr::addr_of_mut!((*slf).3) + }; + candidate.reborrow().project(project) + }; + as ::zerocopy::TryFromBytes>::is_bit_valid( + field_candidate, + ) + } && { + let field_candidate = unsafe { + let project = |slf: *mut Self| { + ::zerocopy::util::macro_util::core_reexport::ptr::addr_of_mut!((*slf).4) + }; + candidate.reborrow().project(project) + }; + , + > as ::zerocopy::TryFromBytes>::is_bit_valid(field_candidate) + } + } } - } - } - #[repr(C)] - #[allow(non_snake_case)] - union ___ZerocopyVariants<'a: 'static, const N: usize, X, Y: Deref> { - __field_StructLike: - core_reexport::mem::ManuallyDrop<___ZerocopyVariantStruct_StructLike<'a, N, X, Y>>, - __field_TupleLike: - core_reexport::mem::ManuallyDrop<___ZerocopyVariantStruct_TupleLike<'a, N, X, Y>>, - __nonempty: (), - } - #[repr(C)] - struct ___ZerocopyRawEnum<'a: 'static, const N: usize, X, Y: Deref> { - tag: ___ZerocopyOuterTag, - variants: ___ZerocopyVariants<'a, N, X, Y>, - } - let tag = { - let tag_ptr = unsafe { - candidate.reborrow().cast_unsized(|p: *mut Self| { p as *mut ___ZerocopyTagPrimitive }) }; - let tag_ptr = unsafe { tag_ptr.assume_initialized() }; - tag_ptr.bikeshed_recall_valid().read_unaligned() - }; - let raw_enum = unsafe { - candidate.cast_unsized(|p: *mut Self| { p as *mut ___ZerocopyRawEnum<'a, N, X, Y> }) - }; - let raw_enum = unsafe { raw_enum.assume_initialized() }; - let variants = unsafe { - raw_enum.project(|p: *mut ___ZerocopyRawEnum<'a, N, X, Y>| { - core_reexport::ptr::addr_of_mut!((*p).variants) - }) - }; - #[allow(non_upper_case_globals)] - match tag { - ___ZEROCOPY_TAG_UnitLike => true, - ___ZEROCOPY_TAG_StructLike => { - let variant = unsafe { - variants.cast_unsized(|p: *mut ___ZerocopyVariants<'a, N, X, Y>| { - p as *mut ___ZerocopyVariantStruct_StructLike<'a, N, X, Y> - }) - }; - let variant = unsafe { variant.assume_initialized() }; - <___ZerocopyVariantStruct_StructLike<'a, N, X, Y> as ::zerocopy ::TryFromBytes>::is_bit_valid ( - variant) + #[repr(C)] + #[allow(non_snake_case)] + union ___ZerocopyVariants<'a: 'static, const N: usize, X, Y: Deref> { + __field_StructLike: + core_reexport::mem::ManuallyDrop<___ZerocopyVariantStruct_StructLike<'a, N, X, Y>>, + __field_TupleLike: + core_reexport::mem::ManuallyDrop<___ZerocopyVariantStruct_TupleLike<'a, N, X, Y>>, + __nonempty: (), + } + #[repr(C)] + struct ___ZerocopyRawEnum<'a: 'static, const N: usize, X, Y: Deref> { + tag: ___ZerocopyOuterTag, + variants: ___ZerocopyVariants<'a, N, X, Y>, } - ___ZEROCOPY_TAG_TupleLike => { - let variant = unsafe { - variants.cast_unsized(|p: *mut ___ZerocopyVariants<'a, N, X, Y>| { - p as *mut ___ZerocopyVariantStruct_TupleLike<'a, N, X, Y> - }) + let tag = { + let tag_ptr = unsafe { + candidate.reborrow().cast_unsized(|p: *mut Self| { p as *mut ___ZerocopyTagPrimitive }) }; - let variant = unsafe { variant.assume_initialized() }; - <___ZerocopyVariantStruct_TupleLike<'a, N, X, Y> as ::zerocopy ::TryFromBytes>::is_bit_valid ( - variant) + let tag_ptr = unsafe { tag_ptr.assume_initialized() }; + tag_ptr.bikeshed_recall_valid().read_unaligned() + }; + let raw_enum = unsafe { + candidate.cast_unsized(|p: *mut Self| { p as *mut ___ZerocopyRawEnum<'a, N, X, Y> }) + }; + let raw_enum = unsafe { raw_enum.assume_initialized() }; + let variants = unsafe { + raw_enum.project(|p: *mut ___ZerocopyRawEnum<'a, N, X, Y>| { + core_reexport::ptr::addr_of_mut!((*p).variants) + }) + }; + #[allow(non_upper_case_globals)] + match tag { + ___ZEROCOPY_TAG_UnitLike => true, + ___ZEROCOPY_TAG_StructLike => { + let variant = unsafe { + variants.cast_unsized(|p: *mut ___ZerocopyVariants<'a, N, X, Y>| { + p as *mut ___ZerocopyVariantStruct_StructLike<'a, N, X, Y> + }) + }; + let variant = unsafe { variant.assume_initialized() }; + <___ZerocopyVariantStruct_StructLike<'a, N, X, Y> as ::zerocopy ::TryFromBytes>::is_bit_valid ( + variant) + } + ___ZEROCOPY_TAG_TupleLike => { + let variant = unsafe { + variants.cast_unsized(|p: *mut ___ZerocopyVariants<'a, N, X, Y>| { + p as *mut ___ZerocopyVariantStruct_TupleLike<'a, N, X, Y> + }) + }; + let variant = unsafe { variant.assume_initialized() }; + <___ZerocopyVariantStruct_TupleLike<'a, N, X, Y> as ::zerocopy ::TryFromBytes>::is_bit_valid ( + variant) + } + _ => false, } - _ => false, } } - } + }; } no_build } @@ -652,285 +688,291 @@ fn test_try_from_bytes_enum() { TupleLike(bool, Y, PhantomData<&'a [(X, Y); N]>), } } expands to { - #[allow(deprecated)] - unsafe impl<'a: 'static, const N: usize, X, Y: Deref> ::zerocopy::TryFromBytes - for ComplexWithGenerics<'a, { N }, X, Y> - where - X: Deref, - u8: ::zerocopy::TryFromBytes, - X: ::zerocopy::TryFromBytes, - X::Target: ::zerocopy::TryFromBytes, - Y::Target: ::zerocopy::TryFromBytes, - [(X, Y); N]: ::zerocopy::TryFromBytes, - bool: ::zerocopy::TryFromBytes, - Y: ::zerocopy::TryFromBytes, - PhantomData<&'a [(X, Y); N]>: ::zerocopy::TryFromBytes, - { - fn only_derive_is_allowed_to_implement_this_trait() {} - fn is_bit_valid<___ZerocopyAliasing>( - mut candidate: ::zerocopy::Maybe<'_, Self, ___ZerocopyAliasing>, - ) -> ::zerocopy::util::macro_util::core_reexport::primitive::bool + const _: () = { + #[allow(deprecated)] + unsafe impl<'a: 'static, const N: usize, X, Y: Deref> ::zerocopy::TryFromBytes + for ComplexWithGenerics<'a, { N }, X, Y> where - ___ZerocopyAliasing: ::zerocopy::pointer::invariant::Aliasing - + ::zerocopy::pointer::invariant::AtLeast<::zerocopy::pointer::invariant::Shared>, + X: Deref, + u8: ::zerocopy::TryFromBytes, + X: ::zerocopy::TryFromBytes, + X::Target: ::zerocopy::TryFromBytes, + Y::Target: ::zerocopy::TryFromBytes, + [(X, Y); N]: ::zerocopy::TryFromBytes, + bool: ::zerocopy::TryFromBytes, + Y: ::zerocopy::TryFromBytes, + PhantomData<&'a [(X, Y); N]>: ::zerocopy::TryFromBytes, { - use ::zerocopy::util::macro_util::core_reexport; - #[repr(u32)] - #[allow(dead_code)] - enum ___ZerocopyTag { - UnitLike, - StructLike, - TupleLike, - } - type ___ZerocopyTagPrimitive = ::zerocopy::util::macro_util::SizeToTag< - { core_reexport::mem::size_of::<___ZerocopyTag>() }, - >; - #[allow(non_upper_case_globals)] - const ___ZEROCOPY_TAG_UnitLike: ___ZerocopyTagPrimitive = - ___ZerocopyTag::UnitLike as ___ZerocopyTagPrimitive; - #[allow(non_upper_case_globals)] - const ___ZEROCOPY_TAG_StructLike: ___ZerocopyTagPrimitive = - ___ZerocopyTag::StructLike as ___ZerocopyTagPrimitive; - #[allow(non_upper_case_globals)] - const ___ZEROCOPY_TAG_TupleLike: ___ZerocopyTagPrimitive = - ___ZerocopyTag::TupleLike as ___ZerocopyTagPrimitive; - type ___ZerocopyOuterTag = (); - type ___ZerocopyInnerTag = ___ZerocopyTag; - #[repr(C)] - #[allow(non_snake_case)] - struct ___ZerocopyVariantStruct_StructLike<'a: 'static, const N: usize, X, Y: Deref>( - core_reexport::mem::MaybeUninit<___ZerocopyInnerTag>, - u8, - X, - X::Target, - Y::Target, - [(X, Y); N], - core_reexport::marker::PhantomData>, - ) - where - X: Deref; - #[allow(deprecated)] - unsafe impl<'a: 'static, const N: usize, X, Y: Deref> ::zerocopy::TryFromBytes - for ___ZerocopyVariantStruct_StructLike<'a, { N }, X, Y> + fn only_derive_is_allowed_to_implement_this_trait() {} + fn is_bit_valid<___ZerocopyAliasing>( + mut candidate: ::zerocopy::Maybe<'_, Self, ___ZerocopyAliasing>, + ) -> ::zerocopy::util::macro_util::core_reexport::primitive::bool where - X: Deref, - core_reexport::mem::MaybeUninit<___ZerocopyInnerTag>: ::zerocopy::TryFromBytes, - u8: ::zerocopy::TryFromBytes, - X: ::zerocopy::TryFromBytes, - X::Target: ::zerocopy::TryFromBytes, - Y::Target: ::zerocopy::TryFromBytes, - [(X, Y); N]: ::zerocopy::TryFromBytes, - core_reexport::marker::PhantomData>: - ::zerocopy::TryFromBytes, + ___ZerocopyAliasing: ::zerocopy::pointer::invariant::Aliasing + + ::zerocopy::pointer::invariant::AtLeast<::zerocopy::pointer::invariant::Shared>, { - fn only_derive_is_allowed_to_implement_this_trait() {} - fn is_bit_valid<___ZerocopyAliasing>( - mut candidate: ::zerocopy::Maybe, - ) -> ::zerocopy::util::macro_util::core_reexport::primitive::bool + use ::zerocopy::util::macro_util::core_reexport; + #[repr(u32)] + #[allow(dead_code)] + enum ___ZerocopyTag { + UnitLike, + StructLike, + TupleLike, + } + type ___ZerocopyTagPrimitive = ::zerocopy::util::macro_util::SizeToTag< + { core_reexport::mem::size_of::<___ZerocopyTag>() }, + >; + #[allow(non_upper_case_globals)] + const ___ZEROCOPY_TAG_UnitLike: ___ZerocopyTagPrimitive = + ___ZerocopyTag::UnitLike as ___ZerocopyTagPrimitive; + #[allow(non_upper_case_globals)] + const ___ZEROCOPY_TAG_StructLike: ___ZerocopyTagPrimitive = + ___ZerocopyTag::StructLike as ___ZerocopyTagPrimitive; + #[allow(non_upper_case_globals)] + const ___ZEROCOPY_TAG_TupleLike: ___ZerocopyTagPrimitive = + ___ZerocopyTag::TupleLike as ___ZerocopyTagPrimitive; + type ___ZerocopyOuterTag = (); + type ___ZerocopyInnerTag = ___ZerocopyTag; + #[repr(C)] + #[allow(non_snake_case)] + struct ___ZerocopyVariantStruct_StructLike<'a: 'static, const N: usize, X, Y: Deref>( + core_reexport::mem::MaybeUninit<___ZerocopyInnerTag>, + u8, + X, + X::Target, + Y::Target, + [(X, Y); N], + core_reexport::marker::PhantomData>, + ) where - ___ZerocopyAliasing: ::zerocopy::pointer::invariant::Aliasing - + ::zerocopy::pointer::invariant::AtLeast<::zerocopy::pointer::invariant::Shared>, - { - true && { - let field_candidate = unsafe { - let project = |slf: *mut Self| { - ::zerocopy::util::macro_util::core_reexport::ptr::addr_of_mut!((*slf).0) - }; - candidate.reborrow().project(project) - }; - as ::zerocopy::TryFromBytes>::is_bit_valid(field_candidate) - } && { - let field_candidate = unsafe { - let project = |slf: *mut Self| { - ::zerocopy::util::macro_util::core_reexport::ptr::addr_of_mut!((*slf).1) - }; - candidate.reborrow().project(project) - }; - ::is_bit_valid(field_candidate) - } && { - let field_candidate = unsafe { - let project = |slf: *mut Self| { - ::zerocopy::util::macro_util::core_reexport::ptr::addr_of_mut!((*slf).2) - }; - candidate.reborrow().project(project) - }; - ::is_bit_valid(field_candidate) - } && { - let field_candidate = unsafe { - let project = |slf: *mut Self| { - ::zerocopy::util::macro_util::core_reexport::ptr::addr_of_mut!((*slf).3) - }; - candidate.reborrow().project(project) - }; - ::is_bit_valid(field_candidate) - } && { - let field_candidate = unsafe { - let project = |slf: *mut Self| { - ::zerocopy::util::macro_util::core_reexport::ptr::addr_of_mut!((*slf).4) - }; - candidate.reborrow().project(project) - }; - ::is_bit_valid(field_candidate) - } && { - let field_candidate = unsafe { - let project = |slf: *mut Self| { - ::zerocopy::util::macro_util::core_reexport::ptr::addr_of_mut!((*slf).5) - }; - candidate.reborrow().project(project) - }; - <[(X, Y); N] as ::zerocopy::TryFromBytes>::is_bit_valid(field_candidate) - } && { - let field_candidate = unsafe { - let project = |slf: *mut Self| { - ::zerocopy::util::macro_util::core_reexport::ptr::addr_of_mut!((*slf).6) - }; - candidate.reborrow().project(project) - }; - , - > as ::zerocopy::TryFromBytes>::is_bit_valid(field_candidate) + X: Deref; + const _: () = { + #[allow(deprecated)] + unsafe impl<'a: 'static, const N: usize, X, Y: Deref> ::zerocopy::TryFromBytes + for ___ZerocopyVariantStruct_StructLike<'a, { N }, X, Y> + where + X: Deref, + core_reexport::mem::MaybeUninit<___ZerocopyInnerTag>: ::zerocopy::TryFromBytes, + u8: ::zerocopy::TryFromBytes, + X: ::zerocopy::TryFromBytes, + X::Target: ::zerocopy::TryFromBytes, + Y::Target: ::zerocopy::TryFromBytes, + [(X, Y); N]: ::zerocopy::TryFromBytes, + core_reexport::marker::PhantomData>: + ::zerocopy::TryFromBytes, + { + fn only_derive_is_allowed_to_implement_this_trait() {} + fn is_bit_valid<___ZerocopyAliasing>( + mut candidate: ::zerocopy::Maybe, + ) -> ::zerocopy::util::macro_util::core_reexport::primitive::bool + where + ___ZerocopyAliasing: ::zerocopy::pointer::invariant::Aliasing + + ::zerocopy::pointer::invariant::AtLeast<::zerocopy::pointer::invariant::Shared>, + { + true && { + let field_candidate = unsafe { + let project = |slf: *mut Self| { + ::zerocopy::util::macro_util::core_reexport::ptr::addr_of_mut!((*slf).0) + }; + candidate.reborrow().project(project) + }; + as ::zerocopy::TryFromBytes>::is_bit_valid(field_candidate) + } && { + let field_candidate = unsafe { + let project = |slf: *mut Self| { + ::zerocopy::util::macro_util::core_reexport::ptr::addr_of_mut!((*slf).1) + }; + candidate.reborrow().project(project) + }; + ::is_bit_valid(field_candidate) + } && { + let field_candidate = unsafe { + let project = |slf: *mut Self| { + ::zerocopy::util::macro_util::core_reexport::ptr::addr_of_mut!((*slf).2) + }; + candidate.reborrow().project(project) + }; + ::is_bit_valid(field_candidate) + } && { + let field_candidate = unsafe { + let project = |slf: *mut Self| { + ::zerocopy::util::macro_util::core_reexport::ptr::addr_of_mut!((*slf).3) + }; + candidate.reborrow().project(project) + }; + ::is_bit_valid(field_candidate) + } && { + let field_candidate = unsafe { + let project = |slf: *mut Self| { + ::zerocopy::util::macro_util::core_reexport::ptr::addr_of_mut!((*slf).4) + }; + candidate.reborrow().project(project) + }; + ::is_bit_valid(field_candidate) + } && { + let field_candidate = unsafe { + let project = |slf: *mut Self| { + ::zerocopy::util::macro_util::core_reexport::ptr::addr_of_mut!((*slf).5) + }; + candidate.reborrow().project(project) + }; + <[(X, Y); N] as ::zerocopy::TryFromBytes>::is_bit_valid(field_candidate) + } && { + let field_candidate = unsafe { + let project = |slf: *mut Self| { + ::zerocopy::util::macro_util::core_reexport::ptr::addr_of_mut!((*slf).6) + }; + candidate.reborrow().project(project) + }; + , + > as ::zerocopy::TryFromBytes>::is_bit_valid(field_candidate) + } + } } - } - } - #[repr(C)] - #[allow(non_snake_case)] - struct ___ZerocopyVariantStruct_TupleLike<'a: 'static, const N: usize, X, Y: Deref>( - core_reexport::mem::MaybeUninit<___ZerocopyInnerTag>, - bool, - Y, - PhantomData<&'a [(X, Y); N]>, - core_reexport::marker::PhantomData>, - ) - where - X: Deref; - #[allow(deprecated)] - unsafe impl<'a: 'static, const N: usize, X, Y: Deref> ::zerocopy::TryFromBytes - for ___ZerocopyVariantStruct_TupleLike<'a, { N }, X, Y> - where - X: Deref, - core_reexport::mem::MaybeUninit<___ZerocopyInnerTag>: ::zerocopy::TryFromBytes, - bool: ::zerocopy::TryFromBytes, - Y: ::zerocopy::TryFromBytes, - PhantomData<&'a [(X, Y); N]>: ::zerocopy::TryFromBytes, - core_reexport::marker::PhantomData>: - ::zerocopy::TryFromBytes, - { - fn only_derive_is_allowed_to_implement_this_trait() {} - fn is_bit_valid<___ZerocopyAliasing>( - mut candidate: ::zerocopy::Maybe, - ) -> ::zerocopy::util::macro_util::core_reexport::primitive::bool + }; + #[repr(C)] + #[allow(non_snake_case)] + struct ___ZerocopyVariantStruct_TupleLike<'a: 'static, const N: usize, X, Y: Deref>( + core_reexport::mem::MaybeUninit<___ZerocopyInnerTag>, + bool, + Y, + PhantomData<&'a [(X, Y); N]>, + core_reexport::marker::PhantomData>, + ) where - ___ZerocopyAliasing: ::zerocopy::pointer::invariant::Aliasing - + ::zerocopy::pointer::invariant::AtLeast<::zerocopy::pointer::invariant::Shared>, - { - true && { - let field_candidate = unsafe { - let project = |slf: *mut Self| { - ::zerocopy::util::macro_util::core_reexport::ptr::addr_of_mut!((*slf).0) - }; - candidate.reborrow().project(project) - }; - as ::zerocopy::TryFromBytes>::is_bit_valid(field_candidate) - } && { - let field_candidate = unsafe { - let project = |slf: *mut Self| { - ::zerocopy::util::macro_util::core_reexport::ptr::addr_of_mut!((*slf).1) - }; - candidate.reborrow().project(project) - }; - ::is_bit_valid(field_candidate) - } && { - let field_candidate = unsafe { - let project = |slf: *mut Self| { - ::zerocopy::util::macro_util::core_reexport::ptr::addr_of_mut!((*slf).2) - }; - candidate.reborrow().project(project) - }; - ::is_bit_valid(field_candidate) - } && { - let field_candidate = unsafe { - let project = |slf: *mut Self| { - ::zerocopy::util::macro_util::core_reexport::ptr::addr_of_mut!((*slf).3) - }; - candidate.reborrow().project(project) - }; - as ::zerocopy::TryFromBytes>::is_bit_valid( - field_candidate, - ) - } && { - let field_candidate = unsafe { - let project = |slf: *mut Self| { - ::zerocopy::util::macro_util::core_reexport::ptr::addr_of_mut!((*slf).4) - }; - candidate.reborrow().project(project) - }; - , - > as ::zerocopy::TryFromBytes>::is_bit_valid(field_candidate) + X: Deref; + const _: () = { + #[allow(deprecated)] + unsafe impl<'a: 'static, const N: usize, X, Y: Deref> ::zerocopy::TryFromBytes + for ___ZerocopyVariantStruct_TupleLike<'a, { N }, X, Y> + where + X: Deref, + core_reexport::mem::MaybeUninit<___ZerocopyInnerTag>: ::zerocopy::TryFromBytes, + bool: ::zerocopy::TryFromBytes, + Y: ::zerocopy::TryFromBytes, + PhantomData<&'a [(X, Y); N]>: ::zerocopy::TryFromBytes, + core_reexport::marker::PhantomData>: + ::zerocopy::TryFromBytes, + { + fn only_derive_is_allowed_to_implement_this_trait() {} + fn is_bit_valid<___ZerocopyAliasing>( + mut candidate: ::zerocopy::Maybe, + ) -> ::zerocopy::util::macro_util::core_reexport::primitive::bool + where + ___ZerocopyAliasing: ::zerocopy::pointer::invariant::Aliasing + + ::zerocopy::pointer::invariant::AtLeast<::zerocopy::pointer::invariant::Shared>, + { + true && { + let field_candidate = unsafe { + let project = |slf: *mut Self| { + ::zerocopy::util::macro_util::core_reexport::ptr::addr_of_mut!((*slf).0) + }; + candidate.reborrow().project(project) + }; + as ::zerocopy::TryFromBytes>::is_bit_valid(field_candidate) + } && { + let field_candidate = unsafe { + let project = |slf: *mut Self| { + ::zerocopy::util::macro_util::core_reexport::ptr::addr_of_mut!((*slf).1) + }; + candidate.reborrow().project(project) + }; + ::is_bit_valid(field_candidate) + } && { + let field_candidate = unsafe { + let project = |slf: *mut Self| { + ::zerocopy::util::macro_util::core_reexport::ptr::addr_of_mut!((*slf).2) + }; + candidate.reborrow().project(project) + }; + ::is_bit_valid(field_candidate) + } && { + let field_candidate = unsafe { + let project = |slf: *mut Self| { + ::zerocopy::util::macro_util::core_reexport::ptr::addr_of_mut!((*slf).3) + }; + candidate.reborrow().project(project) + }; + as ::zerocopy::TryFromBytes>::is_bit_valid( + field_candidate, + ) + } && { + let field_candidate = unsafe { + let project = |slf: *mut Self| { + ::zerocopy::util::macro_util::core_reexport::ptr::addr_of_mut!((*slf).4) + }; + candidate.reborrow().project(project) + }; + , + > as ::zerocopy::TryFromBytes>::is_bit_valid(field_candidate) + } + } } - } - } - #[repr(C)] - #[allow(non_snake_case)] - union ___ZerocopyVariants<'a: 'static, const N: usize, X, Y: Deref> { - __field_StructLike: - core_reexport::mem::ManuallyDrop<___ZerocopyVariantStruct_StructLike<'a, N, X, Y>>, - __field_TupleLike: - core_reexport::mem::ManuallyDrop<___ZerocopyVariantStruct_TupleLike<'a, N, X, Y>>, - __nonempty: (), - } - #[repr(C)] - struct ___ZerocopyRawEnum<'a: 'static, const N: usize, X, Y: Deref> { - tag: ___ZerocopyOuterTag, - variants: ___ZerocopyVariants<'a, N, X, Y>, - } - let tag = { - let tag_ptr = unsafe { - candidate.reborrow().cast_unsized(|p: *mut Self| { p as *mut ___ZerocopyTagPrimitive }) }; - let tag_ptr = unsafe { tag_ptr.assume_initialized() }; - tag_ptr.bikeshed_recall_valid().read_unaligned() - }; - let raw_enum = unsafe { - candidate.cast_unsized(|p: *mut Self| { p as *mut ___ZerocopyRawEnum<'a, N, X, Y> }) - }; - let raw_enum = unsafe { raw_enum.assume_initialized() }; - let variants = unsafe { - raw_enum.project(|p: *mut ___ZerocopyRawEnum<'a, N, X, Y>| { - core_reexport::ptr::addr_of_mut!((*p).variants) - }) - }; - #[allow(non_upper_case_globals)] - match tag { - ___ZEROCOPY_TAG_UnitLike => true, - ___ZEROCOPY_TAG_StructLike => { - let variant = unsafe { - variants.cast_unsized(|p: *mut ___ZerocopyVariants<'a, N, X, Y>| { - p as *mut ___ZerocopyVariantStruct_StructLike<'a, N, X, Y> - }) - }; - let variant = unsafe { variant.assume_initialized() }; - <___ZerocopyVariantStruct_StructLike<'a, N, X, Y> as ::zerocopy ::TryFromBytes>::is_bit_valid ( - variant) + #[repr(C)] + #[allow(non_snake_case)] + union ___ZerocopyVariants<'a: 'static, const N: usize, X, Y: Deref> { + __field_StructLike: + core_reexport::mem::ManuallyDrop<___ZerocopyVariantStruct_StructLike<'a, N, X, Y>>, + __field_TupleLike: + core_reexport::mem::ManuallyDrop<___ZerocopyVariantStruct_TupleLike<'a, N, X, Y>>, + __nonempty: (), } - ___ZEROCOPY_TAG_TupleLike => { - let variant = unsafe { - variants.cast_unsized(|p: *mut ___ZerocopyVariants<'a, N, X, Y>| { - p as *mut ___ZerocopyVariantStruct_TupleLike<'a, N, X, Y> - }) + #[repr(C)] + struct ___ZerocopyRawEnum<'a: 'static, const N: usize, X, Y: Deref> { + tag: ___ZerocopyOuterTag, + variants: ___ZerocopyVariants<'a, N, X, Y>, + } + let tag = { + let tag_ptr = unsafe { + candidate.reborrow().cast_unsized(|p: *mut Self| { p as *mut ___ZerocopyTagPrimitive }) }; - let variant = unsafe { variant.assume_initialized() }; - <___ZerocopyVariantStruct_TupleLike<'a, N, X, Y> as ::zerocopy ::TryFromBytes>::is_bit_valid ( - variant) + let tag_ptr = unsafe { tag_ptr.assume_initialized() }; + tag_ptr.bikeshed_recall_valid().read_unaligned() + }; + let raw_enum = unsafe { + candidate.cast_unsized(|p: *mut Self| { p as *mut ___ZerocopyRawEnum<'a, N, X, Y> }) + }; + let raw_enum = unsafe { raw_enum.assume_initialized() }; + let variants = unsafe { + raw_enum.project(|p: *mut ___ZerocopyRawEnum<'a, N, X, Y>| { + core_reexport::ptr::addr_of_mut!((*p).variants) + }) + }; + #[allow(non_upper_case_globals)] + match tag { + ___ZEROCOPY_TAG_UnitLike => true, + ___ZEROCOPY_TAG_StructLike => { + let variant = unsafe { + variants.cast_unsized(|p: *mut ___ZerocopyVariants<'a, N, X, Y>| { + p as *mut ___ZerocopyVariantStruct_StructLike<'a, N, X, Y> + }) + }; + let variant = unsafe { variant.assume_initialized() }; + <___ZerocopyVariantStruct_StructLike<'a, N, X, Y> as ::zerocopy ::TryFromBytes>::is_bit_valid ( + variant) + } + ___ZEROCOPY_TAG_TupleLike => { + let variant = unsafe { + variants.cast_unsized(|p: *mut ___ZerocopyVariants<'a, N, X, Y>| { + p as *mut ___ZerocopyVariantStruct_TupleLike<'a, N, X, Y> + }) + }; + let variant = unsafe { variant.assume_initialized() }; + <___ZerocopyVariantStruct_TupleLike<'a, N, X, Y> as ::zerocopy ::TryFromBytes>::is_bit_valid ( + variant) + } + _ => false, } - _ => false, } } - } + }; } no_build } @@ -946,285 +988,291 @@ fn test_try_from_bytes_enum() { TupleLike(bool, Y, PhantomData<&'a [(X, Y); N]>), } } expands to { - #[allow(deprecated)] - unsafe impl<'a: 'static, const N: usize, X, Y: Deref> ::zerocopy::TryFromBytes - for ComplexWithGenerics<'a, { N }, X, Y> - where - X: Deref, - u8: ::zerocopy::TryFromBytes, - X: ::zerocopy::TryFromBytes, - X::Target: ::zerocopy::TryFromBytes, - Y::Target: ::zerocopy::TryFromBytes, - [(X, Y); N]: ::zerocopy::TryFromBytes, - bool: ::zerocopy::TryFromBytes, - Y: ::zerocopy::TryFromBytes, - PhantomData<&'a [(X, Y); N]>: ::zerocopy::TryFromBytes, - { - fn only_derive_is_allowed_to_implement_this_trait() {} - fn is_bit_valid<___ZerocopyAliasing>( - mut candidate: ::zerocopy::Maybe<'_, Self, ___ZerocopyAliasing>, - ) -> ::zerocopy::util::macro_util::core_reexport::primitive::bool + const _: () = { + #[allow(deprecated)] + unsafe impl<'a: 'static, const N: usize, X, Y: Deref> ::zerocopy::TryFromBytes + for ComplexWithGenerics<'a, { N }, X, Y> where - ___ZerocopyAliasing: ::zerocopy::pointer::invariant::Aliasing - + ::zerocopy::pointer::invariant::AtLeast<::zerocopy::pointer::invariant::Shared>, + X: Deref, + u8: ::zerocopy::TryFromBytes, + X: ::zerocopy::TryFromBytes, + X::Target: ::zerocopy::TryFromBytes, + Y::Target: ::zerocopy::TryFromBytes, + [(X, Y); N]: ::zerocopy::TryFromBytes, + bool: ::zerocopy::TryFromBytes, + Y: ::zerocopy::TryFromBytes, + PhantomData<&'a [(X, Y); N]>: ::zerocopy::TryFromBytes, { - use ::zerocopy::util::macro_util::core_reexport; - #[repr(C)] - #[allow(dead_code)] - enum ___ZerocopyTag { - UnitLike, - StructLike, - TupleLike, - } - type ___ZerocopyTagPrimitive = ::zerocopy::util::macro_util::SizeToTag< - { core_reexport::mem::size_of::<___ZerocopyTag>() }, - >; - #[allow(non_upper_case_globals)] - const ___ZEROCOPY_TAG_UnitLike: ___ZerocopyTagPrimitive = - ___ZerocopyTag::UnitLike as ___ZerocopyTagPrimitive; - #[allow(non_upper_case_globals)] - const ___ZEROCOPY_TAG_StructLike: ___ZerocopyTagPrimitive = - ___ZerocopyTag::StructLike as ___ZerocopyTagPrimitive; - #[allow(non_upper_case_globals)] - const ___ZEROCOPY_TAG_TupleLike: ___ZerocopyTagPrimitive = - ___ZerocopyTag::TupleLike as ___ZerocopyTagPrimitive; - type ___ZerocopyOuterTag = ___ZerocopyTag; - type ___ZerocopyInnerTag = (); - #[repr(C)] - #[allow(non_snake_case)] - struct ___ZerocopyVariantStruct_StructLike<'a: 'static, const N: usize, X, Y: Deref>( - core_reexport::mem::MaybeUninit<___ZerocopyInnerTag>, - u8, - X, - X::Target, - Y::Target, - [(X, Y); N], - core_reexport::marker::PhantomData>, - ) - where - X: Deref; - #[allow(deprecated)] - unsafe impl<'a: 'static, const N: usize, X, Y: Deref> ::zerocopy::TryFromBytes - for ___ZerocopyVariantStruct_StructLike<'a, { N }, X, Y> + fn only_derive_is_allowed_to_implement_this_trait() {} + fn is_bit_valid<___ZerocopyAliasing>( + mut candidate: ::zerocopy::Maybe<'_, Self, ___ZerocopyAliasing>, + ) -> ::zerocopy::util::macro_util::core_reexport::primitive::bool where - X: Deref, - core_reexport::mem::MaybeUninit<___ZerocopyInnerTag>: ::zerocopy::TryFromBytes, - u8: ::zerocopy::TryFromBytes, - X: ::zerocopy::TryFromBytes, - X::Target: ::zerocopy::TryFromBytes, - Y::Target: ::zerocopy::TryFromBytes, - [(X, Y); N]: ::zerocopy::TryFromBytes, - core_reexport::marker::PhantomData>: - ::zerocopy::TryFromBytes, + ___ZerocopyAliasing: ::zerocopy::pointer::invariant::Aliasing + + ::zerocopy::pointer::invariant::AtLeast<::zerocopy::pointer::invariant::Shared>, { - fn only_derive_is_allowed_to_implement_this_trait() {} - fn is_bit_valid<___ZerocopyAliasing>( - mut candidate: ::zerocopy::Maybe, - ) -> ::zerocopy::util::macro_util::core_reexport::primitive::bool + use ::zerocopy::util::macro_util::core_reexport; + #[repr(C)] + #[allow(dead_code)] + enum ___ZerocopyTag { + UnitLike, + StructLike, + TupleLike, + } + type ___ZerocopyTagPrimitive = ::zerocopy::util::macro_util::SizeToTag< + { core_reexport::mem::size_of::<___ZerocopyTag>() }, + >; + #[allow(non_upper_case_globals)] + const ___ZEROCOPY_TAG_UnitLike: ___ZerocopyTagPrimitive = + ___ZerocopyTag::UnitLike as ___ZerocopyTagPrimitive; + #[allow(non_upper_case_globals)] + const ___ZEROCOPY_TAG_StructLike: ___ZerocopyTagPrimitive = + ___ZerocopyTag::StructLike as ___ZerocopyTagPrimitive; + #[allow(non_upper_case_globals)] + const ___ZEROCOPY_TAG_TupleLike: ___ZerocopyTagPrimitive = + ___ZerocopyTag::TupleLike as ___ZerocopyTagPrimitive; + type ___ZerocopyOuterTag = ___ZerocopyTag; + type ___ZerocopyInnerTag = (); + #[repr(C)] + #[allow(non_snake_case)] + struct ___ZerocopyVariantStruct_StructLike<'a: 'static, const N: usize, X, Y: Deref>( + core_reexport::mem::MaybeUninit<___ZerocopyInnerTag>, + u8, + X, + X::Target, + Y::Target, + [(X, Y); N], + core_reexport::marker::PhantomData>, + ) where - ___ZerocopyAliasing: ::zerocopy::pointer::invariant::Aliasing - + ::zerocopy::pointer::invariant::AtLeast<::zerocopy::pointer::invariant::Shared>, - { - true && { - let field_candidate = unsafe { - let project = |slf: *mut Self| { - ::zerocopy::util::macro_util::core_reexport::ptr::addr_of_mut!((*slf).0) - }; - candidate.reborrow().project(project) - }; - as ::zerocopy::TryFromBytes>::is_bit_valid(field_candidate) - } && { - let field_candidate = unsafe { - let project = |slf: *mut Self| { - ::zerocopy::util::macro_util::core_reexport::ptr::addr_of_mut!((*slf).1) - }; - candidate.reborrow().project(project) - }; - ::is_bit_valid(field_candidate) - } && { - let field_candidate = unsafe { - let project = |slf: *mut Self| { - ::zerocopy::util::macro_util::core_reexport::ptr::addr_of_mut!((*slf).2) - }; - candidate.reborrow().project(project) - }; - ::is_bit_valid(field_candidate) - } && { - let field_candidate = unsafe { - let project = |slf: *mut Self| { - ::zerocopy::util::macro_util::core_reexport::ptr::addr_of_mut!((*slf).3) - }; - candidate.reborrow().project(project) - }; - ::is_bit_valid(field_candidate) - } && { - let field_candidate = unsafe { - let project = |slf: *mut Self| { - ::zerocopy::util::macro_util::core_reexport::ptr::addr_of_mut!((*slf).4) - }; - candidate.reborrow().project(project) - }; - ::is_bit_valid(field_candidate) - } && { - let field_candidate = unsafe { - let project = |slf: *mut Self| { - ::zerocopy::util::macro_util::core_reexport::ptr::addr_of_mut!((*slf).5) - }; - candidate.reborrow().project(project) - }; - <[(X, Y); N] as ::zerocopy::TryFromBytes>::is_bit_valid(field_candidate) - } && { - let field_candidate = unsafe { - let project = |slf: *mut Self| { - ::zerocopy::util::macro_util::core_reexport::ptr::addr_of_mut!((*slf).6) - }; - candidate.reborrow().project(project) - }; - , - > as ::zerocopy::TryFromBytes>::is_bit_valid(field_candidate) + X: Deref; + const _: () = { + #[allow(deprecated)] + unsafe impl<'a: 'static, const N: usize, X, Y: Deref> ::zerocopy::TryFromBytes + for ___ZerocopyVariantStruct_StructLike<'a, { N }, X, Y> + where + X: Deref, + core_reexport::mem::MaybeUninit<___ZerocopyInnerTag>: ::zerocopy::TryFromBytes, + u8: ::zerocopy::TryFromBytes, + X: ::zerocopy::TryFromBytes, + X::Target: ::zerocopy::TryFromBytes, + Y::Target: ::zerocopy::TryFromBytes, + [(X, Y); N]: ::zerocopy::TryFromBytes, + core_reexport::marker::PhantomData>: + ::zerocopy::TryFromBytes, + { + fn only_derive_is_allowed_to_implement_this_trait() {} + fn is_bit_valid<___ZerocopyAliasing>( + mut candidate: ::zerocopy::Maybe, + ) -> ::zerocopy::util::macro_util::core_reexport::primitive::bool + where + ___ZerocopyAliasing: ::zerocopy::pointer::invariant::Aliasing + + ::zerocopy::pointer::invariant::AtLeast<::zerocopy::pointer::invariant::Shared>, + { + true && { + let field_candidate = unsafe { + let project = |slf: *mut Self| { + ::zerocopy::util::macro_util::core_reexport::ptr::addr_of_mut!((*slf).0) + }; + candidate.reborrow().project(project) + }; + as ::zerocopy::TryFromBytes>::is_bit_valid(field_candidate) + } && { + let field_candidate = unsafe { + let project = |slf: *mut Self| { + ::zerocopy::util::macro_util::core_reexport::ptr::addr_of_mut!((*slf).1) + }; + candidate.reborrow().project(project) + }; + ::is_bit_valid(field_candidate) + } && { + let field_candidate = unsafe { + let project = |slf: *mut Self| { + ::zerocopy::util::macro_util::core_reexport::ptr::addr_of_mut!((*slf).2) + }; + candidate.reborrow().project(project) + }; + ::is_bit_valid(field_candidate) + } && { + let field_candidate = unsafe { + let project = |slf: *mut Self| { + ::zerocopy::util::macro_util::core_reexport::ptr::addr_of_mut!((*slf).3) + }; + candidate.reborrow().project(project) + }; + ::is_bit_valid(field_candidate) + } && { + let field_candidate = unsafe { + let project = |slf: *mut Self| { + ::zerocopy::util::macro_util::core_reexport::ptr::addr_of_mut!((*slf).4) + }; + candidate.reborrow().project(project) + }; + ::is_bit_valid(field_candidate) + } && { + let field_candidate = unsafe { + let project = |slf: *mut Self| { + ::zerocopy::util::macro_util::core_reexport::ptr::addr_of_mut!((*slf).5) + }; + candidate.reborrow().project(project) + }; + <[(X, Y); N] as ::zerocopy::TryFromBytes>::is_bit_valid(field_candidate) + } && { + let field_candidate = unsafe { + let project = |slf: *mut Self| { + ::zerocopy::util::macro_util::core_reexport::ptr::addr_of_mut!((*slf).6) + }; + candidate.reborrow().project(project) + }; + , + > as ::zerocopy::TryFromBytes>::is_bit_valid(field_candidate) + } + } } - } - } - #[repr(C)] - #[allow(non_snake_case)] - struct ___ZerocopyVariantStruct_TupleLike<'a: 'static, const N: usize, X, Y: Deref>( - core_reexport::mem::MaybeUninit<___ZerocopyInnerTag>, - bool, - Y, - PhantomData<&'a [(X, Y); N]>, - core_reexport::marker::PhantomData>, - ) - where - X: Deref; - #[allow(deprecated)] - unsafe impl<'a: 'static, const N: usize, X, Y: Deref> ::zerocopy::TryFromBytes - for ___ZerocopyVariantStruct_TupleLike<'a, { N }, X, Y> - where - X: Deref, - core_reexport::mem::MaybeUninit<___ZerocopyInnerTag>: ::zerocopy::TryFromBytes, - bool: ::zerocopy::TryFromBytes, - Y: ::zerocopy::TryFromBytes, - PhantomData<&'a [(X, Y); N]>: ::zerocopy::TryFromBytes, - core_reexport::marker::PhantomData>: - ::zerocopy::TryFromBytes, - { - fn only_derive_is_allowed_to_implement_this_trait() {} - fn is_bit_valid<___ZerocopyAliasing>( - mut candidate: ::zerocopy::Maybe, - ) -> ::zerocopy::util::macro_util::core_reexport::primitive::bool + }; + #[repr(C)] + #[allow(non_snake_case)] + struct ___ZerocopyVariantStruct_TupleLike<'a: 'static, const N: usize, X, Y: Deref>( + core_reexport::mem::MaybeUninit<___ZerocopyInnerTag>, + bool, + Y, + PhantomData<&'a [(X, Y); N]>, + core_reexport::marker::PhantomData>, + ) where - ___ZerocopyAliasing: ::zerocopy::pointer::invariant::Aliasing - + ::zerocopy::pointer::invariant::AtLeast<::zerocopy::pointer::invariant::Shared>, - { - true && { - let field_candidate = unsafe { - let project = |slf: *mut Self| { - ::zerocopy::util::macro_util::core_reexport::ptr::addr_of_mut!((*slf).0) - }; - candidate.reborrow().project(project) - }; - as ::zerocopy::TryFromBytes>::is_bit_valid(field_candidate) - } && { - let field_candidate = unsafe { - let project = |slf: *mut Self| { - ::zerocopy::util::macro_util::core_reexport::ptr::addr_of_mut!((*slf).1) - }; - candidate.reborrow().project(project) - }; - ::is_bit_valid(field_candidate) - } && { - let field_candidate = unsafe { - let project = |slf: *mut Self| { - ::zerocopy::util::macro_util::core_reexport::ptr::addr_of_mut!((*slf).2) - }; - candidate.reborrow().project(project) - }; - ::is_bit_valid(field_candidate) - } && { - let field_candidate = unsafe { - let project = |slf: *mut Self| { - ::zerocopy::util::macro_util::core_reexport::ptr::addr_of_mut!((*slf).3) - }; - candidate.reborrow().project(project) - }; - as ::zerocopy::TryFromBytes>::is_bit_valid( - field_candidate, - ) - } && { - let field_candidate = unsafe { - let project = |slf: *mut Self| { - ::zerocopy::util::macro_util::core_reexport::ptr::addr_of_mut!((*slf).4) - }; - candidate.reborrow().project(project) - }; - , - > as ::zerocopy::TryFromBytes>::is_bit_valid(field_candidate) + X: Deref; + const _: () = { + #[allow(deprecated)] + unsafe impl<'a: 'static, const N: usize, X, Y: Deref> ::zerocopy::TryFromBytes + for ___ZerocopyVariantStruct_TupleLike<'a, { N }, X, Y> + where + X: Deref, + core_reexport::mem::MaybeUninit<___ZerocopyInnerTag>: ::zerocopy::TryFromBytes, + bool: ::zerocopy::TryFromBytes, + Y: ::zerocopy::TryFromBytes, + PhantomData<&'a [(X, Y); N]>: ::zerocopy::TryFromBytes, + core_reexport::marker::PhantomData>: + ::zerocopy::TryFromBytes, + { + fn only_derive_is_allowed_to_implement_this_trait() {} + fn is_bit_valid<___ZerocopyAliasing>( + mut candidate: ::zerocopy::Maybe, + ) -> ::zerocopy::util::macro_util::core_reexport::primitive::bool + where + ___ZerocopyAliasing: ::zerocopy::pointer::invariant::Aliasing + + ::zerocopy::pointer::invariant::AtLeast<::zerocopy::pointer::invariant::Shared>, + { + true && { + let field_candidate = unsafe { + let project = |slf: *mut Self| { + ::zerocopy::util::macro_util::core_reexport::ptr::addr_of_mut!((*slf).0) + }; + candidate.reborrow().project(project) + }; + as ::zerocopy::TryFromBytes>::is_bit_valid(field_candidate) + } && { + let field_candidate = unsafe { + let project = |slf: *mut Self| { + ::zerocopy::util::macro_util::core_reexport::ptr::addr_of_mut!((*slf).1) + }; + candidate.reborrow().project(project) + }; + ::is_bit_valid(field_candidate) + } && { + let field_candidate = unsafe { + let project = |slf: *mut Self| { + ::zerocopy::util::macro_util::core_reexport::ptr::addr_of_mut!((*slf).2) + }; + candidate.reborrow().project(project) + }; + ::is_bit_valid(field_candidate) + } && { + let field_candidate = unsafe { + let project = |slf: *mut Self| { + ::zerocopy::util::macro_util::core_reexport::ptr::addr_of_mut!((*slf).3) + }; + candidate.reborrow().project(project) + }; + as ::zerocopy::TryFromBytes>::is_bit_valid( + field_candidate, + ) + } && { + let field_candidate = unsafe { + let project = |slf: *mut Self| { + ::zerocopy::util::macro_util::core_reexport::ptr::addr_of_mut!((*slf).4) + }; + candidate.reborrow().project(project) + }; + , + > as ::zerocopy::TryFromBytes>::is_bit_valid(field_candidate) + } + } } - } - } - #[repr(C)] - #[allow(non_snake_case)] - union ___ZerocopyVariants<'a: 'static, const N: usize, X, Y: Deref> { - __field_StructLike: - core_reexport::mem::ManuallyDrop<___ZerocopyVariantStruct_StructLike<'a, N, X, Y>>, - __field_TupleLike: - core_reexport::mem::ManuallyDrop<___ZerocopyVariantStruct_TupleLike<'a, N, X, Y>>, - __nonempty: (), - } - #[repr(C)] - struct ___ZerocopyRawEnum<'a: 'static, const N: usize, X, Y: Deref> { - tag: ___ZerocopyOuterTag, - variants: ___ZerocopyVariants<'a, N, X, Y>, - } - let tag = { - let tag_ptr = unsafe { - candidate.reborrow().cast_unsized(|p: *mut Self| { p as *mut ___ZerocopyTagPrimitive }) }; - let tag_ptr = unsafe { tag_ptr.assume_initialized() }; - tag_ptr.bikeshed_recall_valid().read_unaligned() - }; - let raw_enum = unsafe { - candidate.cast_unsized(|p: *mut Self| { p as *mut ___ZerocopyRawEnum<'a, N, X, Y> }) - }; - let raw_enum = unsafe { raw_enum.assume_initialized() }; - let variants = unsafe { - raw_enum.project(|p: *mut ___ZerocopyRawEnum<'a, N, X, Y>| { - core_reexport::ptr::addr_of_mut!((*p).variants) - }) - }; - #[allow(non_upper_case_globals)] - match tag { - ___ZEROCOPY_TAG_UnitLike => true, - ___ZEROCOPY_TAG_StructLike => { - let variant = unsafe { - variants.cast_unsized(|p: *mut ___ZerocopyVariants<'a, N, X, Y>| { - p as *mut ___ZerocopyVariantStruct_StructLike<'a, N, X, Y> - }) - }; - let variant = unsafe { variant.assume_initialized() }; - <___ZerocopyVariantStruct_StructLike<'a, N, X, Y> as ::zerocopy ::TryFromBytes>::is_bit_valid ( - variant) + #[repr(C)] + #[allow(non_snake_case)] + union ___ZerocopyVariants<'a: 'static, const N: usize, X, Y: Deref> { + __field_StructLike: + core_reexport::mem::ManuallyDrop<___ZerocopyVariantStruct_StructLike<'a, N, X, Y>>, + __field_TupleLike: + core_reexport::mem::ManuallyDrop<___ZerocopyVariantStruct_TupleLike<'a, N, X, Y>>, + __nonempty: (), } - ___ZEROCOPY_TAG_TupleLike => { - let variant = unsafe { - variants.cast_unsized(|p: *mut ___ZerocopyVariants<'a, N, X, Y>| { - p as *mut ___ZerocopyVariantStruct_TupleLike<'a, N, X, Y> - }) + #[repr(C)] + struct ___ZerocopyRawEnum<'a: 'static, const N: usize, X, Y: Deref> { + tag: ___ZerocopyOuterTag, + variants: ___ZerocopyVariants<'a, N, X, Y>, + } + let tag = { + let tag_ptr = unsafe { + candidate.reborrow().cast_unsized(|p: *mut Self| { p as *mut ___ZerocopyTagPrimitive }) }; - let variant = unsafe { variant.assume_initialized() }; - <___ZerocopyVariantStruct_TupleLike<'a, N, X, Y> as ::zerocopy ::TryFromBytes>::is_bit_valid ( - variant) + let tag_ptr = unsafe { tag_ptr.assume_initialized() }; + tag_ptr.bikeshed_recall_valid().read_unaligned() + }; + let raw_enum = unsafe { + candidate.cast_unsized(|p: *mut Self| { p as *mut ___ZerocopyRawEnum<'a, N, X, Y> }) + }; + let raw_enum = unsafe { raw_enum.assume_initialized() }; + let variants = unsafe { + raw_enum.project(|p: *mut ___ZerocopyRawEnum<'a, N, X, Y>| { + core_reexport::ptr::addr_of_mut!((*p).variants) + }) + }; + #[allow(non_upper_case_globals)] + match tag { + ___ZEROCOPY_TAG_UnitLike => true, + ___ZEROCOPY_TAG_StructLike => { + let variant = unsafe { + variants.cast_unsized(|p: *mut ___ZerocopyVariants<'a, N, X, Y>| { + p as *mut ___ZerocopyVariantStruct_StructLike<'a, N, X, Y> + }) + }; + let variant = unsafe { variant.assume_initialized() }; + <___ZerocopyVariantStruct_StructLike<'a, N, X, Y> as ::zerocopy ::TryFromBytes>::is_bit_valid ( + variant) + } + ___ZEROCOPY_TAG_TupleLike => { + let variant = unsafe { + variants.cast_unsized(|p: *mut ___ZerocopyVariants<'a, N, X, Y>| { + p as *mut ___ZerocopyVariantStruct_TupleLike<'a, N, X, Y> + }) + }; + let variant = unsafe { variant.assume_initialized() }; + <___ZerocopyVariantStruct_TupleLike<'a, N, X, Y> as ::zerocopy ::TryFromBytes>::is_bit_valid ( + variant) + } + _ => false, } - _ => false, } } - } + }; } no_build } } @@ -1495,39 +1543,45 @@ fn test_from_bytes_enum() { Variant255, } } expands to { - #[allow(deprecated)] - unsafe impl ::zerocopy::TryFromBytes for Foo { - fn only_derive_is_allowed_to_implement_this_trait() {} + const _: () = { + #[allow(deprecated)] + unsafe impl ::zerocopy::TryFromBytes for Foo { + fn only_derive_is_allowed_to_implement_this_trait() {} - fn is_bit_valid<___ZerocopyAliasing>( - _candidate: ::zerocopy::Maybe, - ) -> ::zerocopy::util::macro_util::core_reexport::primitive::bool - where - ___ZerocopyAliasing: ::zerocopy::pointer::invariant::Aliasing - + ::zerocopy::pointer::invariant::AtLeast<::zerocopy::pointer::invariant::Shared>, - { - if false { - fn assert_is_from_bytes() - where - T: ::zerocopy::FromBytes, - T: ?::zerocopy::util::macro_util::core_reexport::marker::Sized, - {} - assert_is_from_bytes::(); - } + fn is_bit_valid<___ZerocopyAliasing>( + _candidate: ::zerocopy::Maybe, + ) -> ::zerocopy::util::macro_util::core_reexport::primitive::bool + where + ___ZerocopyAliasing: ::zerocopy::pointer::invariant::Aliasing + + ::zerocopy::pointer::invariant::AtLeast<::zerocopy::pointer::invariant::Shared>, + { + if false { + fn assert_is_from_bytes() + where + T: ::zerocopy::FromBytes, + T: ?::zerocopy::util::macro_util::core_reexport::marker::Sized, + {} + assert_is_from_bytes::(); + } - true + true + } } - } + }; - #[allow(deprecated)] - unsafe impl ::zerocopy::FromZeros for Foo { - fn only_derive_is_allowed_to_implement_this_trait() {} - } + const _: () = { + #[allow(deprecated)] + unsafe impl ::zerocopy::FromZeros for Foo { + fn only_derive_is_allowed_to_implement_this_trait() {} + } + }; - #[allow(deprecated)] - unsafe impl ::zerocopy::FromBytes for Foo { - fn only_derive_is_allowed_to_implement_this_trait() {} - } + const _: () = { + #[allow(deprecated)] + unsafe impl ::zerocopy::FromBytes for Foo { + fn only_derive_is_allowed_to_implement_this_trait() {} + } + }; } no_build } } @@ -1800,20 +1854,22 @@ fn test_try_from_bytes_trivial_is_bit_valid_enum() { Variant255, } } expands to { - #[allow(deprecated)] - unsafe impl ::zerocopy::TryFromBytes for Foo { - fn only_derive_is_allowed_to_implement_this_trait() {} + const _: () = { + #[allow(deprecated)] + unsafe impl ::zerocopy::TryFromBytes for Foo { + fn only_derive_is_allowed_to_implement_this_trait() {} - fn is_bit_valid<___ZerocopyAliasing>( - _candidate: ::zerocopy::Maybe, - ) -> ::zerocopy::util::macro_util::core_reexport::primitive::bool - where - ___ZerocopyAliasing: ::zerocopy::pointer::invariant::Aliasing - + ::zerocopy::pointer::invariant::AtLeast<::zerocopy::pointer::invariant::Shared>, - { - true + fn is_bit_valid<___ZerocopyAliasing>( + _candidate: ::zerocopy::Maybe, + ) -> ::zerocopy::util::macro_util::core_reexport::primitive::bool + where + ___ZerocopyAliasing: ::zerocopy::pointer::invariant::Aliasing + + ::zerocopy::pointer::invariant::AtLeast<::zerocopy::pointer::invariant::Shared>, + { + true + } } - } + }; } no_build } }