From 5e9f693dcb43c35187ca95ce1c824e0cb1d3c4f8 Mon Sep 17 00:00:00 2001 From: Taiki Endo Date: Thu, 4 Jan 2024 21:23:43 +0900 Subject: [PATCH] util: impl From<[T; N]> for Arc<[T]> --- portable-atomic-util/src/arc.rs | 48 ++++++++++++++++++--------------- 1 file changed, 26 insertions(+), 22 deletions(-) diff --git a/portable-atomic-util/src/arc.rs b/portable-atomic-util/src/arc.rs index 3ce767cb..3d4f1efe 100644 --- a/portable-atomic-util/src/arc.rs +++ b/portable-atomic-util/src/arc.rs @@ -2093,28 +2093,32 @@ macro_rules! items { }; } -// TODO: CoerceUnsized is needed to cast Arc<[T; N]> -> Arc<[T]> -// #[cfg(not(portable_atomic_no_min_const_generics))] -// items! { -// impl From<[T; N]> for Arc<[T]> { -// /// Converts a [`[T; N]`](prim@array) into an `Arc<[T]>`. -// /// -// /// The conversion moves the array into a newly allocated `Arc`. -// /// -// /// # Example -// /// -// /// ``` -// /// use portable_atomic_util::Arc; -// /// let original: [i32; 3] = [1, 2, 3]; -// /// let shared: Arc<[i32]> = Arc::from(original); -// /// assert_eq!(&[1, 2, 3], &shared[..]); -// /// ``` -// #[inline] -// fn from(v: [T; N]) -> Self { -// Arc::<[T; N]>::from(v) -// } -// } -// } +#[cfg(not(portable_atomic_no_min_const_generics))] +items! { +impl From<[T; N]> for Arc<[T]> { + /// Converts a [`[T; N]`](prim@array) into an `Arc<[T]>`. + /// + /// The conversion moves the array into a newly allocated `Arc`. + /// + /// # Example + /// + /// ``` + /// use portable_atomic_util::Arc; + /// let original: [i32; 3] = [1, 2, 3]; + /// let shared: Arc<[i32]> = Arc::from(original); + /// assert_eq!(&[1, 2, 3], &shared[..]); + /// ``` + #[inline] + fn from(v: [T; N]) -> Self { + // Casting Arc<[T; N]> -> Arc<[T]> requires unstable CoerceUnsized, so we convert via Box. + // Since the compiler knows the actual size and metadata, the intermediate allocation is + // optimized and generates the same code as when using CoerceUnsized and convert Arc<[T; N]> to Arc<[T]>. + // https://github.com/taiki-e/portable-atomic/issues/143#issuecomment-1866488569 + let v: Box<[T]> = Box::<[T; N]>::from(v); + v.into() + } +} +} #[cfg(not(portable_atomic_no_alloc_layout_extras))] impl From<&[T]> for Arc<[T]> {