about summary refs log tree commit diff
path: root/library/alloc/src
diff options
context:
space:
mode:
authorJacob Pratt <jacob@jhpratt.dev>2024-12-26 21:56:48 -0500
committerGitHub <noreply@github.com>2024-12-26 21:56:48 -0500
commitb618af13cf14171843ec6f62691c5534f44667af (patch)
tree53645915860461d770daeb5f7404df35d05c901c /library/alloc/src
parentb919afa70fe4a77bfdb548a7a54d08803de26842 (diff)
parent00c5289c649394d544b6189e2bcdbcc7ceff49f1 (diff)
downloadrust-b618af13cf14171843ec6f62691c5534f44667af.tar.gz
rust-b618af13cf14171843ec6f62691c5534f44667af.zip
Rollup merge of #134379 - bjoernager:slice-as-array, r=dtolnay
Add `into_array` conversion destructors for `Box`, `Rc`, and `Arc`.

Tracking issue: #133508

This PR adds the `into_array` destructor for `alloc::boxed::Box<[T]>`, `alloc::rc::Rc<[T]>`, and `alloc::sync::Arc<[T]>`.

Note that this PR assumes the initial proposal of these functions returning `Option`. It is still an open question whether this should instead be `Result`. We can, however, easily change this in a follow-up PR with the necessary consensus.
Diffstat (limited to 'library/alloc/src')
-rw-r--r--library/alloc/src/boxed.rs20
-rw-r--r--library/alloc/src/rc.rs20
-rw-r--r--library/alloc/src/sync.rs20
3 files changed, 60 insertions, 0 deletions
diff --git a/library/alloc/src/boxed.rs b/library/alloc/src/boxed.rs
index 23b85fbd4eb..ca3bd24a420 100644
--- a/library/alloc/src/boxed.rs
+++ b/library/alloc/src/boxed.rs
@@ -761,6 +761,26 @@ impl<T> Box<[T]> {
         };
         unsafe { Ok(RawVec::from_raw_parts_in(ptr.as_ptr(), len, Global).into_box(len)) }
     }
+
+    /// Converts the boxed slice into a boxed array.
+    ///
+    /// This operation does not reallocate; the underlying array of the slice is simply reinterpreted as an array type.
+    ///
+    /// If `N` is not exactly equal to the length of `self`, then this method returns `None`.
+    #[unstable(feature = "slice_as_array", issue = "133508")]
+    #[inline]
+    #[must_use]
+    pub fn into_array<const N: usize>(self) -> Option<Box<[T; N]>> {
+        if self.len() == N {
+            let ptr = Self::into_raw(self) as *mut [T; N];
+
+            // SAFETY: The underlying array of a slice has the exact same layout as an actual array `[T; N]` if `N` is equal to the slice's length.
+            let me = unsafe { Box::from_raw(ptr) };
+            Some(me)
+        } else {
+            None
+        }
+    }
 }
 
 impl<T, A: Allocator> Box<[T], A> {
diff --git a/library/alloc/src/rc.rs b/library/alloc/src/rc.rs
index b7ec3af9818..e014404eff3 100644
--- a/library/alloc/src/rc.rs
+++ b/library/alloc/src/rc.rs
@@ -1084,6 +1084,26 @@ impl<T> Rc<[T]> {
             ))
         }
     }
+
+    /// Converts the reference-counted slice into a reference-counted array.
+    ///
+    /// This operation does not reallocate; the underlying array of the slice is simply reinterpreted as an array type.
+    ///
+    /// If `N` is not exactly equal to the length of `self`, then this method returns `None`.
+    #[unstable(feature = "slice_as_array", issue = "133508")]
+    #[inline]
+    #[must_use]
+    pub fn into_array<const N: usize>(self) -> Option<Rc<[T; N]>> {
+        if self.len() == N {
+            let ptr = Self::into_raw(self) as *const [T; N];
+
+            // SAFETY: The underlying array of a slice has the exact same layout as an actual array `[T; N]` if `N` is equal to the slice's length.
+            let me = unsafe { Rc::from_raw(ptr) };
+            Some(me)
+        } else {
+            None
+        }
+    }
 }
 
 impl<T, A: Allocator> Rc<[T], A> {
diff --git a/library/alloc/src/sync.rs b/library/alloc/src/sync.rs
index 9be0b3e3e88..b34a6d3f660 100644
--- a/library/alloc/src/sync.rs
+++ b/library/alloc/src/sync.rs
@@ -1203,6 +1203,26 @@ impl<T> Arc<[T]> {
             ))
         }
     }
+
+    /// Converts the reference-counted slice into a reference-counted array.
+    ///
+    /// This operation does not reallocate; the underlying array of the slice is simply reinterpreted as an array type.
+    ///
+    /// If `N` is not exactly equal to the length of `self`, then this method returns `None`.
+    #[unstable(feature = "slice_as_array", issue = "133508")]
+    #[inline]
+    #[must_use]
+    pub fn into_array<const N: usize>(self) -> Option<Arc<[T; N]>> {
+        if self.len() == N {
+            let ptr = Self::into_raw(self) as *const [T; N];
+
+            // SAFETY: The underlying array of a slice has the exact same layout as an actual array `[T; N]` if `N` is equal to the slice's length.
+            let me = unsafe { Arc::from_raw(ptr) };
+            Some(me)
+        } else {
+            None
+        }
+    }
 }
 
 impl<T, A: Allocator> Arc<[T], A> {