From 6f31f05aaf8e89f87e01052ba61fa04613b0a090 Mon Sep 17 00:00:00 2001 From: Elichai Turkel Date: Wed, 22 Apr 2020 12:39:29 +0300 Subject: [PATCH 1/2] Add a function to turn Box into Box<[T]> (into_boxed_slice) --- src/liballoc/boxed.rs | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/liballoc/boxed.rs b/src/liballoc/boxed.rs index db7420954a0..5419491fc23 100644 --- a/src/liballoc/boxed.rs +++ b/src/liballoc/boxed.rs @@ -239,6 +239,16 @@ impl Box { pub fn pin(x: T) -> Pin> { (box x).into() } + + /// Converts a `Box` 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) -> 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 Box<[T]> { From 0228ca0c7d07f92d449209fa2eeda9eb72e68f63 Mon Sep 17 00:00:00 2001 From: Elichai Turkel Date: Wed, 22 Apr 2020 17:23:20 +0300 Subject: [PATCH 2/2] Add success and fail tests for into_boxed_slice --- src/test/ui/box-into-boxed-slice-fail.rs | 15 +++++++ src/test/ui/box-into-boxed-slice-fail.stderr | 43 ++++++++++++++++++++ src/test/ui/box-into-boxed-slice.rs | 11 +++++ 3 files changed, 69 insertions(+) create mode 100644 src/test/ui/box-into-boxed-slice-fail.rs create mode 100644 src/test/ui/box-into-boxed-slice-fail.stderr create mode 100644 src/test/ui/box-into-boxed-slice.rs diff --git a/src/test/ui/box-into-boxed-slice-fail.rs b/src/test/ui/box-into-boxed-slice-fail.rs new file mode 100644 index 00000000000..5f8a3fd9d6a --- /dev/null +++ b/src/test/ui/box-into-boxed-slice-fail.rs @@ -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 = 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 +} diff --git a/src/test/ui/box-into-boxed-slice-fail.stderr b/src/test/ui/box-into-boxed-slice-fail.stderr new file mode 100644 index 00000000000..dfc4999958a --- /dev/null +++ b/src/test/ui/box-into-boxed-slice-fail.stderr @@ -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 + = note: required by `std::boxed::Box::::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 + = 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 + = note: required by `std::boxed::Box::::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 + = 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`. diff --git a/src/test/ui/box-into-boxed-slice.rs b/src/test/ui/box-into-boxed-slice.rs new file mode 100644 index 00000000000..61b3d915253 --- /dev/null +++ b/src/test/ui/box-into-boxed-slice.rs @@ -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); +}