Skip to content
/ rust Public
forked from rust-lang/rust

Commit

Permalink
Rollup merge of rust-lang#134379 - bjoernager:slice-as-array, r=dtolnay
Browse files Browse the repository at this point in the history
Add `into_array` conversion destructors for `Box`, `Rc`, and `Arc`.

Tracking issue: rust-lang#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.
  • Loading branch information
jhpratt authored Dec 27, 2024
2 parents b919afa + 00c5289 commit b618af1
Show file tree
Hide file tree
Showing 3 changed files with 60 additions and 0 deletions.
20 changes: 20 additions & 0 deletions library/alloc/src/boxed.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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> {
Expand Down
20 changes: 20 additions & 0 deletions library/alloc/src/rc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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> {
Expand Down
20 changes: 20 additions & 0 deletions library/alloc/src/sync.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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> {
Expand Down

0 comments on commit b618af1

Please sign in to comment.