Rollup merge of #71421 - elichai:2020-04-boxed-slice, r=sfackler
Add a function to turn Box<T> into Box<[T]> Hi, I think this is very useful, as currently it's not possible in safe rust to do this without re-allocating. an alternative implementation of the same function can be: ```rust pub fn into_boxed_slice<T>(boxed: Box<T>) -> Box<[T]> { unsafe { let slice = slice::from_raw_parts_mut(Box::into_raw(boxed), 1); Box::from_raw(slice) } } ``` The only thing that makes me a little uncomfortable is this line : > The alignment of array types is greater or equal to the alignment of its element type from https://rust-lang.github.io/unsafe-code-guidelines/layout/arrays-and-slices.html But then I see: > The alignment of &T, &mut T, *const T and *mut T are the same, and are at least the word size. > The alignment of &[T] is the word size. from https://rust-lang.github.io/unsafe-code-guidelines/layout/pointers.html#representation So I do believe this is valid(FWIW it also passes in miri https://play.rust-lang.org/?gist=c002b99364ee6b29862aeb3565a91c19)
This commit is contained in:
commit
398d3eeca1
@ -239,6 +239,16 @@ impl<T> Box<T> {
|
||||
pub fn pin(x: T) -> Pin<Box<T>> {
|
||||
(box x).into()
|
||||
}
|
||||
|
||||
/// Converts a `Box<T>` into a `Box<[T]>`
|
||||
///
|
||||
/// This conversion does not allocate on the heap and happens in place.
|
||||
///
|
||||
#[unstable(feature = "box_into_boxed_slice", issue = "71582")]
|
||||
pub fn into_boxed_slice(boxed: Box<T>) -> Box<[T]> {
|
||||
// *mut T and *mut [T; 1] have the same size and alignment
|
||||
unsafe { Box::from_raw(Box::into_raw(boxed) as *mut [T; 1] as *mut [T]) }
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Box<[T]> {
|
||||
|
15
src/test/ui/box-into-boxed-slice-fail.rs
Normal file
15
src/test/ui/box-into-boxed-slice-fail.rs
Normal file
@ -0,0 +1,15 @@
|
||||
// ignore-tidy-linelength
|
||||
#![feature(box_into_boxed_slice)]
|
||||
|
||||
use std::boxed::Box;
|
||||
use std::fmt::Debug;
|
||||
fn main() {
|
||||
let boxed_slice = Box::new([1,2,3]) as Box<[u8]>;
|
||||
let _ = Box::into_boxed_slice(boxed_slice);
|
||||
//~^ ERROR the size for values of type `[u8]` cannot be known at compilation time
|
||||
//~^^ ERROR the size for values of type `[u8]` cannot be known at compilation time
|
||||
let boxed_trait: Box<dyn Debug> = Box::new(5u8);
|
||||
let _ = Box::into_boxed_slice(boxed_trait);
|
||||
//~^ ERROR the size for values of type `dyn std::fmt::Debug` cannot be known at compilation time
|
||||
//~^^ ERROR the size for values of type `dyn std::fmt::Debug` cannot be known at compilation time
|
||||
}
|
43
src/test/ui/box-into-boxed-slice-fail.stderr
Normal file
43
src/test/ui/box-into-boxed-slice-fail.stderr
Normal file
@ -0,0 +1,43 @@
|
||||
error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
|
||||
--> $DIR/box-into-boxed-slice-fail.rs:8:35
|
||||
|
|
||||
LL | let _ = Box::into_boxed_slice(boxed_slice);
|
||||
| ^^^^^^^^^^^ doesn't have a size known at compile-time
|
||||
|
|
||||
= help: the trait `std::marker::Sized` is not implemented for `[u8]`
|
||||
= note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
|
||||
= note: required by `std::boxed::Box::<T>::into_boxed_slice`
|
||||
|
||||
error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
|
||||
--> $DIR/box-into-boxed-slice-fail.rs:8:13
|
||||
|
|
||||
LL | let _ = Box::into_boxed_slice(boxed_slice);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
|
||||
|
|
||||
= help: the trait `std::marker::Sized` is not implemented for `[u8]`
|
||||
= note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
|
||||
= note: slice and array elements must have `Sized` type
|
||||
|
||||
error[E0277]: the size for values of type `dyn std::fmt::Debug` cannot be known at compilation time
|
||||
--> $DIR/box-into-boxed-slice-fail.rs:12:35
|
||||
|
|
||||
LL | let _ = Box::into_boxed_slice(boxed_trait);
|
||||
| ^^^^^^^^^^^ doesn't have a size known at compile-time
|
||||
|
|
||||
= help: the trait `std::marker::Sized` is not implemented for `dyn std::fmt::Debug`
|
||||
= note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
|
||||
= note: required by `std::boxed::Box::<T>::into_boxed_slice`
|
||||
|
||||
error[E0277]: the size for values of type `dyn std::fmt::Debug` cannot be known at compilation time
|
||||
--> $DIR/box-into-boxed-slice-fail.rs:12:13
|
||||
|
|
||||
LL | let _ = Box::into_boxed_slice(boxed_trait);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
|
||||
|
|
||||
= help: the trait `std::marker::Sized` is not implemented for `dyn std::fmt::Debug`
|
||||
= note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
|
||||
= note: slice and array elements must have `Sized` type
|
||||
|
||||
error: aborting due to 4 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0277`.
|
11
src/test/ui/box-into-boxed-slice.rs
Normal file
11
src/test/ui/box-into-boxed-slice.rs
Normal file
@ -0,0 +1,11 @@
|
||||
// run-pass
|
||||
#![feature(box_into_boxed_slice)]
|
||||
|
||||
use std::boxed::Box;
|
||||
fn main() {
|
||||
assert_eq!(Box::into_boxed_slice(Box::new(5u8)), Box::new([5u8]) as Box<[u8]>);
|
||||
assert_eq!(Box::into_boxed_slice(Box::new([25u8])), Box::new([[25u8]]) as Box<[[u8; 1]]>);
|
||||
let a: Box<[Box<[u8; 1]>]> = Box::into_boxed_slice(Box::new(Box::new([5u8])));
|
||||
let b: Box<[Box<[u8; 1]>]> = Box::new([Box::new([5u8])]);
|
||||
assert_eq!(a, b);
|
||||
}
|
Loading…
Reference in New Issue
Block a user