Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
131 changes: 131 additions & 0 deletions src/impls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1005,6 +1005,137 @@ const _: () = unsafe {
// [1] https://doc.rust-lang.org/core/option/enum.Option.html
const _: () = unsafe { unsafe_impl!(T: Immutable => Immutable for Option<T>) };

mod tuples {
use super::*;

/// Generates various trait implementations for tuples.
///
/// # Safety
///
/// `impl_tuple!` should be provided name-number pairs, where each number is
/// the ordinal of the preceding type name.
macro_rules! impl_tuple {
// Entry point.
($($T:ident $I:tt),+ $(,)?) => {
crate::util::macros::__unsafe();
impl_tuple!(@all [] [$($T $I)+]);
};

// Build up the set of tuple types (i.e., `(A,)`, `(A, B)`, `(A, B, C)`,
// etc.) Trait implementations that do not depend on field index may be
// added to this branch.
(@all [$($head_T:ident $head_I:tt)*] [$next_T:ident $next_I:tt $($tail:tt)*]) => {
// SAFETY: If all fields of the tuple `Self` are `Immutable`, so too is `Self`.
unsafe_impl!($($head_T: Immutable,)* $next_T: Immutable => Immutable for ($($head_T,)* $next_T,));

// SAFETY: If all fields in `c` are `is_bit_valid`, so too is `c`.
unsafe_impl!($($head_T: TryFromBytes,)* $next_T: TryFromBytes => TryFromBytes for ($($head_T,)* $next_T,); |c| {
let mut c = c;
$(TryFromBytes::is_bit_valid(c.reborrow().project::<_, { crate::ident_id!($head_I) }>()) &&)*
TryFromBytes::is_bit_valid(c.reborrow().project::<_, { crate::ident_id!($next_I) }>())
});

// SAFETY: If all fields in `Self` are `FromZeros`, so too is `Self`.
unsafe_impl!($($head_T: FromZeros,)* $next_T: FromZeros => FromZeros for ($($head_T,)* $next_T,));

// SAFETY: If all fields in `Self` are `FromBytes`, so too is `Self`.
unsafe_impl!($($head_T: FromBytes,)* $next_T: FromBytes => FromBytes for ($($head_T,)* $next_T,));

// Generate impls that depend on tuple index.
impl_tuple!(@variants
[$($head_T $head_I)* $next_T $next_I]
[]
[$($head_T $head_I)* $next_T $next_I]
);

// Recurse to next tuple size
impl_tuple!(@all [$($head_T $head_I)* $next_T $next_I] [$($tail)*]);
};
(@all [$($head_T:ident $head_I:tt)*] []) => {};

// Emit trait implementations that depend on field index.
(@variants
// The full tuple definition in type–index pairs.
[$($AllT:ident $AllI:tt)+]
// Types before the current index.
[$($BeforeT:ident)*]
// The types and indices at and after the current index.
[$CurrT:ident $CurrI:tt $($AfterT:ident $AfterI:tt)*]
) => {
// SAFETY:
// - `Self` is a struct (albeit anonymous), so `VARIANT_ID` is
// `STRUCT_VARIANT_ID`.
// - `$CurrI` is the field at index `$CurrI`, so `FIELD_ID` is
// `zerocopy::ident_id!($CurrI)`
// - `()` has the same visibility as the `.$CurrI` field (ie, `.0`,
// `.1`, etc)
// - `Type` has the same type as `$CurrI`; i.e., `$CurrT`.
unsafe impl<$($AllT),+> crate::HasField<
(),
{ crate::STRUCT_VARIANT_ID },
{ crate::ident_id!($CurrI)}
> for ($($AllT,)+) {
#[inline]
fn only_derive_is_allowed_to_implement_this_trait()
where
Self: Sized
{}

type Type = $CurrT;

#[inline(always)]
fn project(slf: crate::PtrInner<'_, Self>) -> *mut Self::Type {
let slf = slf.as_non_null().as_ptr();
// SAFETY: `PtrInner` promises it references either a zero-sized
// byte range, or else will reference a byte range that is
// entirely contained within an allocated object. In either
// case, this guarantees that `(*slf).$CurrI` is in-bounds of
// `slf`.
unsafe { core::ptr::addr_of_mut!((*slf).$CurrI) }
}
}

// Recurse to the next index.
impl_tuple!(@variants [$($AllT $AllI)+] [$($BeforeT)* $CurrT] [$($AfterT $AfterI)*]);
};
(@variants [$($AllT:ident $AllI:tt)+] [$($BeforeT:ident)*] []) => {};
}

// SAFETY: `impl_tuple` is provided name-number pairs, where number is the
// ordinal of the name.
#[allow(clippy::multiple_unsafe_ops_per_block)]
const _: () = unsafe {
impl_tuple! {
A 0,
B 1,
C 2,
D 3,
E 4,
F 5,
G 6,
H 7,
I 8,
J 9,
K 10,
L 11,
M 12,
N 13,
O 14,
P 15,
Q 16,
R 17,
S 18,
T 19,
U 20,
V 21,
W 22,
X 23,
Y 24,
Z 25,
};
};
}

// SIMD support
//
// Per the Unsafe Code Guidelines Reference [1]:
Expand Down
14 changes: 7 additions & 7 deletions tests/ui-nightly/diagnostic-not-implemented-from-bytes.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,13 @@ help: the trait `zerocopy::FromBytes` is not implemented for `NotZerocopy`
= note: Consider adding `#[derive(FromBytes)]` to `NotZerocopy`
= help: the following other types implement trait `zerocopy::FromBytes`:
()
AU16
AtomicI16
AtomicI32
AtomicI64
AtomicI8
AtomicIsize
AtomicU16
(A, B)
(A, B, C)
(A, B, C, D)
(A, B, C, D, E)
(A, B, C, D, E, F)
(A, B, C, D, E, F, G)
(A, B, C, D, E, F, G, H)
and $N others
note: required by a bound in `takes_from_bytes`
--> tests/ui-nightly/diagnostic-not-implemented-from-bytes.rs:21:24
Expand Down
14 changes: 7 additions & 7 deletions tests/ui-nightly/diagnostic-not-implemented-from-zeros.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,13 @@ help: the trait `FromZeros` is not implemented for `NotZerocopy`
= note: Consider adding `#[derive(FromZeros)]` to `NotZerocopy`
= help: the following other types implement trait `FromZeros`:
()
*const T
*mut T
AU16
AtomicBool
AtomicI16
AtomicI32
AtomicI64
(A, B)
(A, B, C)
(A, B, C, D)
(A, B, C, D, E)
(A, B, C, D, E, F)
(A, B, C, D, E, F, G)
(A, B, C, D, E, F, G, H)
and $N others
note: required by a bound in `takes_from_zeros`
--> tests/ui-nightly/diagnostic-not-implemented-from-zeros.rs:21:24
Expand Down
10 changes: 5 additions & 5 deletions tests/ui-nightly/diagnostic-not-implemented-immutable.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,11 @@ help: the trait `zerocopy::Immutable` is not implemented for `NotZerocopy`
&T
&mut T
()
*const T
*mut T
AU16
Box<T>
F32<O>
(A, B)
(A, B, C)
(A, B, C, D)
(A, B, C, D, E)
(A, B, C, D, E, F)
and $N others
note: required by a bound in `takes_immutable`
--> tests/ui-nightly/diagnostic-not-implemented-immutable.rs:21:23
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,13 @@ help: the trait `zerocopy::TryFromBytes` is not implemented for `NotZerocopy`
= note: Consider adding `#[derive(TryFromBytes)]` to `NotZerocopy`
= help: the following other types implement trait `zerocopy::TryFromBytes`:
()
*const T
*mut T
AU16
AtomicBool
AtomicI16
AtomicI32
AtomicI64
(A, B)
(A, B, C)
(A, B, C, D)
(A, B, C, D, E)
(A, B, C, D, E, F)
(A, B, C, D, E, F, G)
(A, B, C, D, E, F, G, H)
and $N others
note: required by a bound in `takes_try_from_bytes`
--> tests/ui-nightly/diagnostic-not-implemented-try-from-bytes.rs:21:28
Expand Down
14 changes: 7 additions & 7 deletions tests/ui-nightly/include_value_not_from_bytes.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,13 @@ help: the trait `zerocopy::FromBytes` is not implemented for `NotZerocopy<u32>`
= note: Consider adding `#[derive(FromBytes)]` to `NotZerocopy<u32>`
= help: the following other types implement trait `zerocopy::FromBytes`:
()
AU16
AtomicI16
AtomicI32
AtomicI64
AtomicI8
AtomicIsize
AtomicU16
(A, B)
(A, B, C)
(A, B, C, D)
(A, B, C, D, E)
(A, B, C, D, E, F)
(A, B, C, D, E, F, G)
(A, B, C, D, E, F, G, H)
and $N others
note: required by a bound in `NOT_FROM_BYTES::transmute`
--> tests/ui-nightly/include_value_not_from_bytes.rs:19:42
Expand Down
14 changes: 7 additions & 7 deletions tests/ui-nightly/transmute-dst-not-frombytes.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,13 @@ help: the trait `zerocopy::FromBytes` is not implemented for `NotZerocopy`
= note: Consider adding `#[derive(FromBytes)]` to `NotZerocopy`
= help: the following other types implement trait `zerocopy::FromBytes`:
()
AU16
AtomicI16
AtomicI32
AtomicI64
AtomicI8
AtomicIsize
AtomicU16
(A, B)
(A, B, C)
(A, B, C, D)
(A, B, C, D, E)
(A, B, C, D, E, F)
(A, B, C, D, E, F, G)
(A, B, C, D, E, F, G, H)
and $N others
note: required by a bound in `DST_NOT_FROM_BYTES::transmute`
--> tests/ui-nightly/transmute-dst-not-frombytes.rs:19:41
Expand Down
14 changes: 7 additions & 7 deletions tests/ui-nightly/transmute-mut-dst-not-frombytes.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,13 @@ help: the trait `FromBytes` is not implemented for `Dst`
= note: Consider adding `#[derive(FromBytes)]` to `Dst`
= help: the following other types implement trait `FromBytes`:
()
AtomicI16
AtomicI32
AtomicI64
AtomicI8
AtomicIsize
AtomicU16
AtomicU32
(A, B)
(A, B, C)
(A, B, C, D)
(A, B, C, D, E)
(A, B, C, D, E, F)
(A, B, C, D, E, F, G)
(A, B, C, D, E, F, G, H)
and $N others
note: required by a bound in `Wrap::<&'a mut Src, &'a mut Dst>::transmute_mut`
--> src/util/macro_util.rs
Expand Down
14 changes: 7 additions & 7 deletions tests/ui-nightly/transmute-mut-src-not-frombytes.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,13 @@ help: the trait `FromBytes` is not implemented for `Src`
= note: Consider adding `#[derive(FromBytes)]` to `Src`
= help: the following other types implement trait `FromBytes`:
()
AtomicI16
AtomicI32
AtomicI64
AtomicI8
AtomicIsize
AtomicU16
AtomicU32
(A, B)
(A, B, C)
(A, B, C, D)
(A, B, C, D, E)
(A, B, C, D, E, F)
(A, B, C, D, E, F, G)
(A, B, C, D, E, F, G, H)
and $N others
note: required by a bound in `Wrap::<&'a mut Src, &'a mut Dst>::transmute_mut`
--> src/util/macro_util.rs
Expand Down
14 changes: 7 additions & 7 deletions tests/ui-nightly/transmute-ref-dst-not-frombytes.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,13 @@ help: the trait `zerocopy::FromBytes` is not implemented for `Dst`
= note: Consider adding `#[derive(FromBytes)]` to `Dst`
= help: the following other types implement trait `zerocopy::FromBytes`:
()
AU16
AtomicI16
AtomicI32
AtomicI64
AtomicI8
AtomicIsize
AtomicU16
(A, B)
(A, B, C)
(A, B, C, D)
(A, B, C, D, E)
(A, B, C, D, E, F)
(A, B, C, D, E, F, G)
(A, B, C, D, E, F, G, H)
and $N others
note: required by a bound in `AssertDstIsFromBytes`
--> tests/ui-nightly/transmute-ref-dst-not-frombytes.rs:23:34
Expand Down
10 changes: 5 additions & 5 deletions tests/ui-nightly/transmute-ref-dst-not-nocell.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,11 @@ help: the trait `zerocopy::Immutable` is not implemented for `Dst`
&T
&mut T
()
*const T
*mut T
AU16
Box<T>
F32<O>
(A, B)
(A, B, C)
(A, B, C, D)
(A, B, C, D, E)
(A, B, C, D, E, F)
and $N others
note: required by a bound in `AssertDstIsImmutable`
--> tests/ui-nightly/transmute-ref-dst-not-nocell.rs:23:33
Expand Down
20 changes: 10 additions & 10 deletions tests/ui-nightly/transmute-ref-src-not-nocell.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,11 @@ help: the trait `zerocopy::Immutable` is not implemented for `Src`
&T
&mut T
()
*const T
*mut T
AU16
Box<T>
F32<O>
(A, B)
(A, B, C)
(A, B, C, D)
(A, B, C, D, E)
(A, B, C, D, E, F)
and $N others
note: required by a bound in `AssertSrcIsImmutable`
--> tests/ui-nightly/transmute-ref-src-not-nocell.rs:23:34
Expand All @@ -46,11 +46,11 @@ help: the trait `zerocopy::Immutable` is not implemented for `Src`
&T
&mut T
()
*const T
*mut T
AU16
Box<T>
F32<O>
(A, B)
(A, B, C)
(A, B, C, D)
(A, B, C, D, E)
(A, B, C, D, E, F)
and $N others
note: required by a bound in `AssertSrcIsImmutable`
--> tests/ui-nightly/transmute-ref-src-not-nocell.rs:23:34
Expand Down
Loading
Loading