Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add positive and negative trait impl tests for SIMD types #130

Closed
joshlf opened this issue Nov 8, 2022 · 7 comments
Closed

Add positive and negative trait impl tests for SIMD types #130

joshlf opened this issue Nov 8, 2022 · 7 comments
Assignees
Labels
compatibility-nonbreaking Changes that are (likely to be) non-breaking experience-easy This issue is easy, and shouldn't require much experience help wanted Extra attention is needed

Comments

@joshlf
Copy link
Member

joshlf commented Nov 8, 2022

We have tests to ensure that our implementations of FromBytes, AsBytes, and Unaligned for various primitive does not regress:

zerocopy/src/lib.rs

Lines 4512 to 4517 in 3bb9a54

assert_impls!((): FromZeroes, FromBytes, AsBytes, Unaligned);
assert_impls!(u8: FromZeroes, FromBytes, AsBytes, Unaligned);
assert_impls!(i8: FromZeroes, FromBytes, AsBytes, Unaligned);
assert_impls!(u16: FromZeroes, FromBytes, AsBytes, !Unaligned);
assert_impls!(i16: FromZeroes, FromBytes, AsBytes, !Unaligned);
assert_impls!(u32: FromZeroes, FromBytes, AsBytes, !Unaligned);

We should have similar tests for our implementations (or lack thereof) for SIMD types.

Mentorship Instructions

To do this, we will be adding tests at the end of test_impls:

zerocopy/src/lib.rs

Lines 4488 to 4584 in b083f1f

#[test]
fn test_impls() {
// Asserts that `$ty` implements any `$trait` and doesn't implement any
// `!$trait`. Note that all `$trait`s must come before any `!$trait`s.
macro_rules! assert_impls {
($ty:ty: $trait:ident) => {
#[allow(dead_code)]
const _: () = { static_assertions::assert_impl_all!($ty: $trait); };
};
($ty:ty: !$trait:ident) => {
#[allow(dead_code)]
const _: () = { static_assertions::assert_not_impl_any!($ty: $trait); };
};
($ty:ty: $($trait:ident),* $(,)? $(!$negative_trait:ident),*) => {
$(
assert_impls!($ty: $trait);
)*
$(
assert_impls!($ty: !$negative_trait);
)*
};
}
assert_impls!((): FromZeroes, FromBytes, AsBytes, Unaligned);
assert_impls!(u8: FromZeroes, FromBytes, AsBytes, Unaligned);
assert_impls!(i8: FromZeroes, FromBytes, AsBytes, Unaligned);
assert_impls!(u16: FromZeroes, FromBytes, AsBytes, !Unaligned);
assert_impls!(i16: FromZeroes, FromBytes, AsBytes, !Unaligned);
assert_impls!(u32: FromZeroes, FromBytes, AsBytes, !Unaligned);
assert_impls!(i32: FromZeroes, FromBytes, AsBytes, !Unaligned);
assert_impls!(u64: FromZeroes, FromBytes, AsBytes, !Unaligned);
assert_impls!(i64: FromZeroes, FromBytes, AsBytes, !Unaligned);
assert_impls!(u128: FromZeroes, FromBytes, AsBytes, !Unaligned);
assert_impls!(i128: FromZeroes, FromBytes, AsBytes, !Unaligned);
assert_impls!(usize: FromZeroes, FromBytes, AsBytes, !Unaligned);
assert_impls!(isize: FromZeroes, FromBytes, AsBytes, !Unaligned);
assert_impls!(f32: FromZeroes, FromBytes, AsBytes, !Unaligned);
assert_impls!(f64: FromZeroes, FromBytes, AsBytes, !Unaligned);
assert_impls!(bool: FromZeroes, AsBytes, Unaligned, !FromBytes);
assert_impls!(char: FromZeroes, AsBytes, !FromBytes, !Unaligned);
assert_impls!(str: FromZeroes, AsBytes, Unaligned, !FromBytes);
assert_impls!(NonZeroU8: AsBytes, Unaligned, !FromZeroes, !FromBytes);
assert_impls!(NonZeroI8: AsBytes, Unaligned, !FromZeroes, !FromBytes);
assert_impls!(NonZeroU16: AsBytes, !FromZeroes, !FromBytes, !Unaligned);
assert_impls!(NonZeroI16: AsBytes, !FromZeroes, !FromBytes, !Unaligned);
assert_impls!(NonZeroU32: AsBytes, !FromZeroes, !FromBytes, !Unaligned);
assert_impls!(NonZeroI32: AsBytes, !FromZeroes, !FromBytes, !Unaligned);
assert_impls!(NonZeroU64: AsBytes, !FromZeroes, !FromBytes, !Unaligned);
assert_impls!(NonZeroI64: AsBytes, !FromZeroes, !FromBytes, !Unaligned);
assert_impls!(NonZeroU128: AsBytes, !FromZeroes, !FromBytes, !Unaligned);
assert_impls!(NonZeroI128: AsBytes, !FromZeroes, !FromBytes, !Unaligned);
assert_impls!(NonZeroUsize: AsBytes, !FromZeroes, !FromBytes, !Unaligned);
assert_impls!(NonZeroIsize: AsBytes, !FromZeroes, !FromBytes, !Unaligned);
assert_impls!(Option<NonZeroU8>: FromZeroes, FromBytes, AsBytes, Unaligned);
assert_impls!(Option<NonZeroI8>: FromZeroes, FromBytes, AsBytes, Unaligned);
assert_impls!(Option<NonZeroU16>: FromZeroes, FromBytes, AsBytes, !Unaligned);
assert_impls!(Option<NonZeroI16>: FromZeroes, FromBytes, AsBytes, !Unaligned);
assert_impls!(Option<NonZeroU32>: FromZeroes, FromBytes, AsBytes, !Unaligned);
assert_impls!(Option<NonZeroI32>: FromZeroes, FromBytes, AsBytes, !Unaligned);
assert_impls!(Option<NonZeroU64>: FromZeroes, FromBytes, AsBytes, !Unaligned);
assert_impls!(Option<NonZeroI64>: FromZeroes, FromBytes, AsBytes, !Unaligned);
assert_impls!(Option<NonZeroU128>: FromZeroes, FromBytes, AsBytes, !Unaligned);
assert_impls!(Option<NonZeroI128>: FromZeroes, FromBytes, AsBytes, !Unaligned);
assert_impls!(Option<NonZeroUsize>: FromZeroes, FromBytes, AsBytes, !Unaligned);
assert_impls!(Option<NonZeroIsize>: FromZeroes, FromBytes, AsBytes, !Unaligned);
// Implements none of the ZC traits.
struct NotZerocopy;
assert_impls!(PhantomData<NotZerocopy>: FromZeroes, FromBytes, AsBytes, Unaligned);
assert_impls!(PhantomData<[u8]>: FromZeroes, FromBytes, AsBytes, Unaligned);
assert_impls!(ManuallyDrop<u8>: FromZeroes, FromBytes, AsBytes, Unaligned);
assert_impls!(ManuallyDrop<[u8]>: FromZeroes, FromBytes, AsBytes, Unaligned);
assert_impls!(ManuallyDrop<NotZerocopy>: !FromZeroes, !FromBytes, !AsBytes, !Unaligned);
assert_impls!(ManuallyDrop<[NotZerocopy]>: !FromZeroes, !FromBytes, !AsBytes, !Unaligned);
assert_impls!(MaybeUninit<u8>: FromZeroes, FromBytes, Unaligned, !AsBytes);
assert_impls!(MaybeUninit<NotZerocopy>: !FromZeroes, !FromBytes, !AsBytes, !Unaligned);
assert_impls!(Wrapping<u8>: FromZeroes, FromBytes, AsBytes, Unaligned);
assert_impls!(Wrapping<NotZerocopy>: !FromZeroes, !FromBytes, !AsBytes, !Unaligned);
assert_impls!(Unalign<u8>: FromZeroes, FromBytes, AsBytes, Unaligned);
assert_impls!(Unalign<NotZerocopy>: Unaligned, !FromZeroes, !FromBytes, !AsBytes);
assert_impls!([u8]: FromZeroes, FromBytes, AsBytes, Unaligned);
assert_impls!([NotZerocopy]: !FromZeroes, !FromBytes, !AsBytes, !Unaligned);
assert_impls!([u8; 0]: FromZeroes, FromBytes, AsBytes, Unaligned);
assert_impls!([NotZerocopy; 0]: !FromZeroes, !FromBytes, !AsBytes, !Unaligned);
assert_impls!([u8; 1]: FromZeroes, FromBytes, AsBytes, Unaligned);
assert_impls!([NotZerocopy; 1]: !FromZeroes, !FromBytes, !AsBytes, !Unaligned);
}

At the bottom of that test function, create a new block annotated with #[cfg(simd)]; e.g.:

#[cfg(feature = "simd")]
{
    /* everything else will go in this block */
}

Then, add a macro definition like this:

/// Tests that the given SIMD types (belonging to some given architecture)
/// implement exactly the expected set of traits.
macro_rules! test_simd_arch_mod {
    ($arch:ident, $($typ:ident),*) => {
        {
            use core::arch::$arch::{$($typ),*};
            use crate::*;
            $( assert_impls!($ty: KnownLayout, FromZeroes, FromBytes, AsBytes, !Unaligned); )*
        }
    };
}

Finally, invoke the macro for each of the SIMD-supporting architectures (see here); e.g.:

#[cfg(target_arch = "x86")]
test_simd_arch_mod!(x86, __m128, __m128d, __m128i, __m256, __m256d, __m256i);
#[cfg(target_arch = "x86_64")]
test_simd_arch_mod!(x86_64, __m128, __m128d, __m128i, __m256, __m256d, __m256i);

/* and so on */
@joshlf joshlf changed the title Add tests for which traits aren't implemented for which types Add positive and negative trait impl tests for SIMD types Nov 8, 2022
@joshlf joshlf added the blocking-next-release This issue should be resolved before we release on crates.io label Nov 8, 2022
@joshlf joshlf added the compatibility-nonbreaking Changes that are (likely to be) non-breaking label Aug 12, 2023
@joshlf joshlf mentioned this issue Aug 20, 2023
@joshlf joshlf added experience-easy This issue is easy, and shouldn't require much experience help wanted Extra attention is needed and removed blocking-next-release This issue should be resolved before we release on crates.io labels Aug 28, 2023
@Sh0g0-1758
Copy link
Contributor

Hey, can I work on this issue?

@shyamjayakannan
Copy link

Hi, are you looking for a test similar to the one for primitives, to be written within the simd module following all the impls?

@jswrenn
Copy link
Collaborator

jswrenn commented Oct 10, 2023

Apologies, everyone — we'd like to take a slightly different approach. I've updated the issue accordingly.

@jswrenn
Copy link
Collaborator

jswrenn commented Oct 10, 2023

@shyamjayakannan: I'll assign this to @Sh0g0-1758 since they commented first, but you're welcome to take it if they don't end up working on it.

@Sh0g0-1758
Copy link
Contributor

thanks, @jswrenn, I will make sure to complete it.

@Sh0g0-1758
Copy link
Contributor

@jswrenn , I have made a PR. Kindly review it and suggest changes.

@joshlf
Copy link
Member Author

joshlf commented Oct 17, 2023

Closed by #487.

@joshlf joshlf closed this as completed Oct 17, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
compatibility-nonbreaking Changes that are (likely to be) non-breaking experience-easy This issue is easy, and shouldn't require much experience help wanted Extra attention is needed
Projects
None yet
Development

No branches or pull requests

4 participants