diff --git a/crates/core_arch/src/macros.rs b/crates/core_arch/src/macros.rs index f59e278bb7..e00b433536 100644 --- a/crates/core_arch/src/macros.rs +++ b/crates/core_arch/src/macros.rs @@ -132,7 +132,7 @@ macro_rules! types { impl crate::fmt::Debug for $name { #[inline] fn fmt(&self, f: &mut crate::fmt::Formatter<'_>) -> crate::fmt::Result { - crate::core_arch::simd::debug_simd_finish(f, stringify!($name), self.0) + crate::core_arch::simd::debug_simd_finish(f, stringify!($name), self.as_array()) } } )*); diff --git a/crates/core_arch/src/simd.rs b/crates/core_arch/src/simd.rs index 29e4b3e7a2..25834943f0 100644 --- a/crates/core_arch/src/simd.rs +++ b/crates/core_arch/src/simd.rs @@ -5,7 +5,7 @@ macro_rules! simd_ty { ($id:ident [$elem_type:ty ; $len:literal]: $($param_name:ident),*) => { #[repr(simd)] - #[derive(Copy, Clone, Debug, PartialEq)] + #[derive(Copy, Clone)] pub(crate) struct $id([$elem_type; $len]); #[allow(clippy::use_self)] @@ -38,13 +38,32 @@ macro_rules! simd_ty { /// Use for testing only. // FIXME: Workaround rust@60637 #[inline(always)] - pub(crate) fn extract(self, index: usize) -> $elem_type { - assert!(index < $len); - // Now that we know this is in-bounds, use pointer arithmetic to access the right element. - let self_ptr = &self as *const Self as *const $elem_type; - unsafe { - self_ptr.add(index).read() - } + pub(crate) fn extract(&self, index: usize) -> $elem_type { + self.as_array()[index] + } + + #[inline] + pub(crate) fn as_array(&self) -> &[$elem_type; $len] { + let simd_ptr: *const Self = self; + let array_ptr: *const [$elem_type; $len] = simd_ptr.cast(); + // SAFETY: We can always read the prefix of a simd type as an array. + // There might be more padding afterwards for some widths, but + // that's not a problem for reading less than that. + unsafe { &*array_ptr } + } + } + + impl core::cmp::PartialEq for $id { + #[inline] + fn eq(&self, other: &Self) -> bool { + self.as_array() == other.as_array() + } + } + + impl core::fmt::Debug for $id { + #[inline] + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + debug_simd_finish(f, stringify!($id), self.as_array()) } } } @@ -53,7 +72,7 @@ macro_rules! simd_ty { macro_rules! simd_m_ty { ($id:ident [$elem_type:ident ; $len:literal]: $($param_name:ident),*) => { #[repr(simd)] - #[derive(Copy, Clone, Debug, PartialEq)] + #[derive(Copy, Clone)] pub(crate) struct $id([$elem_type; $len]); #[allow(clippy::use_self)] @@ -79,6 +98,30 @@ macro_rules! simd_m_ty { // a simd type with exactly one element. unsafe { simd_shuffle!(one, one, [0; $len]) } } + + #[inline] + pub(crate) fn as_array(&self) -> &[$elem_type; $len] { + let simd_ptr: *const Self = self; + let array_ptr: *const [$elem_type; $len] = simd_ptr.cast(); + // SAFETY: We can always read the prefix of a simd type as an array. + // There might be more padding afterwards for some widths, but + // that's not a problem for reading less than that. + unsafe { &*array_ptr } + } + } + + impl core::cmp::PartialEq for $id { + #[inline] + fn eq(&self, other: &Self) -> bool { + self.as_array() == other.as_array() + } + } + + impl core::fmt::Debug for $id { + #[inline] + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + debug_simd_finish(f, stringify!($id), self.as_array()) + } } } } @@ -968,7 +1011,7 @@ simd_ty!( pub(crate) fn debug_simd_finish( formatter: &mut crate::fmt::Formatter<'_>, type_name: &str, - array: [T; N], + array: &[T; N], ) -> crate::fmt::Result { crate::fmt::Formatter::debug_tuple_fields_finish( formatter,