diff --git a/hybrid-array/src/lib.rs b/hybrid-array/src/lib.rs index 5ed07abf..6b6132c9 100644 --- a/hybrid-array/src/lib.rs +++ b/hybrid-array/src/lib.rs @@ -102,10 +102,7 @@ where // TODO(tarcieri): deprecate this before the v0.2 release // #[deprecated(since = "0.2.0", note = "use TryFrom instead")] #[inline] - pub fn ref_from_slice<'a>(slice: &'a [T]) -> &'a Self - where - &'a Self: TryFrom<&'a [T], Error = TryFromSliceError>, - { + pub fn ref_from_slice(slice: &[T]) -> &Self { slice.try_into().expect("slice length mismatch") } @@ -117,10 +114,7 @@ where // TODO(tarcieri): deprecate this before the v0.2 release // #[deprecated(since = "0.2.0", note = "use TryFrom instead")] #[inline] - pub fn ref_from_mut_slice<'a>(slice: &'a mut [T]) -> &'a mut Self - where - &'a mut Self: TryFrom<&'a mut [T], Error = TryFromSliceError>, - { + pub fn ref_from_mut_slice(slice: &mut [T]) -> &mut Self { slice.try_into().expect("slice length mismatch") } @@ -134,9 +128,9 @@ where #[inline] pub fn clone_from_slice(slice: &[T]) -> Self where - T: Clone, + Self: Clone, { - Self::from_fn(|n| slice[n].clone()) + slice.try_into().expect("slice length mismatch") } /// Concatenates `self` with `other`. @@ -508,10 +502,10 @@ where } } -impl<'a, T, U, const N: usize> TryFrom<&'a [T]> for Array +impl<'a, T, U> TryFrom<&'a [T]> for Array where - Self: ArrayOps + Clone, - U: ArraySize = [T; N]>, + Self: Clone, + U: ArraySize, { type Error = TryFromSliceError; @@ -521,37 +515,35 @@ where } } -impl<'a, T, U, const N: usize> TryFrom<&'a [T]> for &'a Array +impl<'a, T, U> TryFrom<&'a [T]> for &'a Array where - Array: ArrayOps, - U: ArraySize = [T; N]>, + U: ArraySize, { type Error = TryFromSliceError; #[inline] fn try_from(slice: &'a [T]) -> Result { - let array_ref = <&'a [T; N]>::try_from(slice)?; + check_slice_length::(slice)?; // SAFETY: `Array` is a `repr(transparent)` newtype for a core // array with length checked above. - Ok(unsafe { &*(array_ref.as_ptr() as *const Array) }) + Ok(unsafe { &*(slice.as_ptr() as *const Array) }) } } -impl<'a, T, U, const N: usize> TryFrom<&'a mut [T]> for &'a mut Array +impl<'a, T, U> TryFrom<&'a mut [T]> for &'a mut Array where - Array: ArrayOps, - U: ArraySize = [T; N]>, + U: ArraySize, { type Error = TryFromSliceError; #[inline] fn try_from(slice: &'a mut [T]) -> Result { - let array_ref = <&'a mut [T; N]>::try_from(slice)?; + check_slice_length::(slice)?; // SAFETY: `Array` is a `repr(transparent)` newtype for a core // array with length checked above. - Ok(unsafe { &mut *(array_ref.as_ptr() as *mut Array) }) + Ok(unsafe { &mut *(slice.as_ptr() as *mut Array) }) } } @@ -574,6 +566,22 @@ where { } +/// Generate a [`TryFromSliceError`] if the slice doesn't match the given length. +#[cfg_attr(debug_assertions, allow(clippy::panic_in_result_fn))] +fn check_slice_length(slice: &[T]) -> Result<(), TryFromSliceError> { + debug_assert_eq!(Array::<(), U>::default().len(), U::USIZE); + + if slice.len() != U::USIZE { + // Hack: `TryFromSliceError` lacks a public constructor + <&[T; 1]>::try_from([].as_slice())?; + + #[cfg(debug_assertions)] + unreachable!(); + } + + Ok(()) +} + /// Array operations which are const generic over a given array size. pub trait ArrayOps: Borrow<[T; N]>