Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Constify Box<T, A> methods #91884

Merged
merged 3 commits into from
Jan 4, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 18 additions & 5 deletions library/alloc/src/alloc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -323,17 +323,21 @@ unsafe fn exchange_malloc(size: usize, align: usize) -> *mut u8 {

#[cfg_attr(not(test), lang = "box_free")]
#[inline]
#[rustc_const_unstable(feature = "const_box", issue = "92521")]
// This signature has to be the same as `Box`, otherwise an ICE will happen.
// When an additional parameter to `Box` is added (like `A: Allocator`), this has to be added here as
// well.
// For example if `Box` is changed to `struct Box<T: ?Sized, A: Allocator>(Unique<T>, A)`,
// this function has to be changed to `fn box_free<T: ?Sized, A: Allocator>(Unique<T>, A)` as well.
pub(crate) unsafe fn box_free<T: ?Sized, A: Allocator>(ptr: Unique<T>, alloc: A) {
pub(crate) const unsafe fn box_free<T: ?Sized, A: ~const Allocator + ~const Drop>(
ptr: Unique<T>,
alloc: A,
) {
unsafe {
let size = size_of_val(ptr.as_ref());
let align = min_align_of_val(ptr.as_ref());
let layout = Layout::from_size_align_unchecked(size, align);
alloc.deallocate(ptr.cast().into(), layout)
alloc.deallocate(From::from(ptr.cast()), layout)
}
}

Expand Down Expand Up @@ -361,13 +365,22 @@ extern "Rust" {
/// [`set_alloc_error_hook`]: ../../std/alloc/fn.set_alloc_error_hook.html
/// [`take_alloc_error_hook`]: ../../std/alloc/fn.take_alloc_error_hook.html
#[stable(feature = "global_alloc", since = "1.28.0")]
#[rustc_const_unstable(feature = "const_alloc_error", issue = "92523")]
#[cfg(all(not(no_global_oom_handling), not(test)))]
#[rustc_allocator_nounwind]
#[cold]
pub fn handle_alloc_error(layout: Layout) -> ! {
unsafe {
__rust_alloc_error_handler(layout.size(), layout.align());
pub const fn handle_alloc_error(layout: Layout) -> ! {
const fn ct_error(_: Layout) -> ! {
panic!("allocation failed");
}

fn rt_error(layout: Layout) -> ! {
unsafe {
__rust_alloc_error_handler(layout.size(), layout.align());
}
}

unsafe { core::intrinsics::const_eval_select((layout,), ct_error, rt_error) }
}

// For alloc test `std::alloc::handle_alloc_error` can be used directly.
Expand Down
92 changes: 68 additions & 24 deletions library/alloc/src/boxed.rs
Original file line number Diff line number Diff line change
Expand Up @@ -346,9 +346,13 @@ impl<T, A: Allocator> Box<T, A> {
/// ```
#[cfg(not(no_global_oom_handling))]
#[unstable(feature = "allocator_api", issue = "32838")]
#[rustc_const_unstable(feature = "const_box", issue = "92521")]
#[must_use]
#[inline]
pub fn new_in(x: T, alloc: A) -> Self {
pub const fn new_in(x: T, alloc: A) -> Self
where
A: ~const Allocator + ~const Drop,
oli-obk marked this conversation as resolved.
Show resolved Hide resolved
{
let mut boxed = Self::new_uninit_in(alloc);
unsafe {
boxed.as_mut_ptr().write(x);
Expand All @@ -372,8 +376,13 @@ impl<T, A: Allocator> Box<T, A> {
/// # Ok::<(), std::alloc::AllocError>(())
/// ```
#[unstable(feature = "allocator_api", issue = "32838")]
#[rustc_const_unstable(feature = "const_box", issue = "92521")]
#[inline]
pub fn try_new_in(x: T, alloc: A) -> Result<Self, AllocError> {
pub const fn try_new_in(x: T, alloc: A) -> Result<Self, AllocError>
where
T: ~const Drop,
A: ~const Allocator + ~const Drop,
{
let mut boxed = Self::try_new_uninit_in(alloc)?;
unsafe {
boxed.as_mut_ptr().write(x);
Expand Down Expand Up @@ -402,10 +411,14 @@ impl<T, A: Allocator> Box<T, A> {
/// assert_eq!(*five, 5)
/// ```
#[unstable(feature = "allocator_api", issue = "32838")]
#[rustc_const_unstable(feature = "const_box", issue = "92521")]
#[cfg(not(no_global_oom_handling))]
#[must_use]
// #[unstable(feature = "new_uninit", issue = "63291")]
pub fn new_uninit_in(alloc: A) -> Box<mem::MaybeUninit<T>, A> {
pub const fn new_uninit_in(alloc: A) -> Box<mem::MaybeUninit<T>, A>
where
A: ~const Allocator + ~const Drop,
{
let layout = Layout::new::<mem::MaybeUninit<T>>();
// NOTE: Prefer match over unwrap_or_else since closure sometimes not inlineable.
// That would make code size bigger.
Expand Down Expand Up @@ -439,7 +452,11 @@ impl<T, A: Allocator> Box<T, A> {
/// ```
#[unstable(feature = "allocator_api", issue = "32838")]
// #[unstable(feature = "new_uninit", issue = "63291")]
pub fn try_new_uninit_in(alloc: A) -> Result<Box<mem::MaybeUninit<T>, A>, AllocError> {
#[rustc_const_unstable(feature = "const_box", issue = "92521")]
pub const fn try_new_uninit_in(alloc: A) -> Result<Box<mem::MaybeUninit<T>, A>, AllocError>
where
A: ~const Allocator + ~const Drop,
{
let layout = Layout::new::<mem::MaybeUninit<T>>();
let ptr = alloc.allocate(layout)?.cast();
unsafe { Ok(Box::from_raw_in(ptr.as_ptr(), alloc)) }
Expand All @@ -466,10 +483,14 @@ impl<T, A: Allocator> Box<T, A> {
///
/// [zeroed]: mem::MaybeUninit::zeroed
#[unstable(feature = "allocator_api", issue = "32838")]
#[rustc_const_unstable(feature = "const_box", issue = "92521")]
#[cfg(not(no_global_oom_handling))]
// #[unstable(feature = "new_uninit", issue = "63291")]
#[must_use]
pub fn new_zeroed_in(alloc: A) -> Box<mem::MaybeUninit<T>, A> {
pub const fn new_zeroed_in(alloc: A) -> Box<mem::MaybeUninit<T>, A>
where
A: ~const Allocator + ~const Drop,
{
let layout = Layout::new::<mem::MaybeUninit<T>>();
// NOTE: Prefer match over unwrap_or_else since closure sometimes not inlineable.
// That would make code size bigger.
Expand Down Expand Up @@ -503,7 +524,11 @@ impl<T, A: Allocator> Box<T, A> {
/// [zeroed]: mem::MaybeUninit::zeroed
#[unstable(feature = "allocator_api", issue = "32838")]
// #[unstable(feature = "new_uninit", issue = "63291")]
pub fn try_new_zeroed_in(alloc: A) -> Result<Box<mem::MaybeUninit<T>, A>, AllocError> {
#[rustc_const_unstable(feature = "const_box", issue = "92521")]
pub const fn try_new_zeroed_in(alloc: A) -> Result<Box<mem::MaybeUninit<T>, A>, AllocError>
where
A: ~const Allocator + ~const Drop,
{
let layout = Layout::new::<mem::MaybeUninit<T>>();
let ptr = alloc.allocate_zeroed(layout)?.cast();
unsafe { Ok(Box::from_raw_in(ptr.as_ptr(), alloc)) }
Expand All @@ -513,20 +538,22 @@ impl<T, A: Allocator> Box<T, A> {
/// `x` will be pinned in memory and unable to be moved.
#[cfg(not(no_global_oom_handling))]
#[unstable(feature = "allocator_api", issue = "32838")]
#[rustc_const_unstable(feature = "const_box", issue = "92521")]
#[must_use]
#[inline(always)]
pub fn pin_in(x: T, alloc: A) -> Pin<Self>
pub const fn pin_in(x: T, alloc: A) -> Pin<Self>
where
A: 'static,
A: 'static + ~const Allocator + ~const Drop,
{
Self::new_in(x, alloc).into()
Self::into_pin(Self::new_in(x, alloc))
}

/// 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: Self) -> Box<[T], A> {
#[rustc_const_unstable(feature = "const_box", issue = "92521")]
pub const fn into_boxed_slice(boxed: Self) -> Box<[T], A> {
let (raw, alloc) = Box::into_raw_with_allocator(boxed);
unsafe { Box::from_raw_in(raw as *mut [T; 1], alloc) }
}
Expand All @@ -543,8 +570,12 @@ impl<T, A: Allocator> Box<T, A> {
/// assert_eq!(Box::into_inner(c), 5);
/// ```
#[unstable(feature = "box_into_inner", issue = "80437")]
#[rustc_const_unstable(feature = "const_box", issue = "92521")]
#[inline]
pub fn into_inner(boxed: Self) -> T {
pub const fn into_inner(boxed: Self) -> T
where
Self: ~const Drop,
{
*boxed
}
}
Expand Down Expand Up @@ -758,8 +789,9 @@ impl<T, A: Allocator> Box<mem::MaybeUninit<T>, A> {
/// assert_eq!(*five, 5)
/// ```
#[unstable(feature = "new_uninit", issue = "63291")]
#[rustc_const_unstable(feature = "const_box", issue = "92521")]
#[inline]
pub unsafe fn assume_init(self) -> Box<T, A> {
pub const unsafe fn assume_init(self) -> Box<T, A> {
let (raw, alloc) = Box::into_raw_with_allocator(self);
unsafe { Box::from_raw_in(raw as *mut T, alloc) }
}
Expand Down Expand Up @@ -792,8 +824,9 @@ impl<T, A: Allocator> Box<mem::MaybeUninit<T>, A> {
/// }
/// ```
#[unstable(feature = "new_uninit", issue = "63291")]
#[rustc_const_unstable(feature = "const_box", issue = "92521")]
#[inline]
pub fn write(mut boxed: Self, value: T) -> Box<T, A> {
pub const fn write(mut boxed: Self, value: T) -> Box<T, A> {
unsafe {
(*boxed).write(value);
boxed.assume_init()
Expand Down Expand Up @@ -938,8 +971,9 @@ impl<T: ?Sized, A: Allocator> Box<T, A> {
/// [memory layout]: self#memory-layout
/// [`Layout`]: crate::Layout
#[unstable(feature = "allocator_api", issue = "32838")]
#[rustc_const_unstable(feature = "const_box", issue = "92521")]
#[inline]
pub unsafe fn from_raw_in(raw: *mut T, alloc: A) -> Self {
pub const unsafe fn from_raw_in(raw: *mut T, alloc: A) -> Self {
Box(unsafe { Unique::new_unchecked(raw) }, alloc)
}

Expand Down Expand Up @@ -1035,8 +1069,9 @@ impl<T: ?Sized, A: Allocator> Box<T, A> {
///
/// [memory layout]: self#memory-layout
#[unstable(feature = "allocator_api", issue = "32838")]
#[rustc_const_unstable(feature = "const_box", issue = "92521")]
#[inline]
pub fn into_raw_with_allocator(b: Self) -> (*mut T, A) {
pub const fn into_raw_with_allocator(b: Self) -> (*mut T, A) {
let (leaked, alloc) = Box::into_unique(b);
(leaked.as_ptr(), alloc)
}
Expand All @@ -1046,9 +1081,10 @@ impl<T: ?Sized, A: Allocator> Box<T, A> {
issue = "none",
reason = "use `Box::leak(b).into()` or `Unique::from(Box::leak(b))` instead"
)]
#[rustc_const_unstable(feature = "const_box", issue = "92521")]
#[inline]
#[doc(hidden)]
pub fn into_unique(b: Self) -> (Unique<T>, A) {
pub const fn into_unique(b: Self) -> (Unique<T>, A) {
// Box is recognized as a "unique pointer" by Stacked Borrows, but internally it is a
// raw pointer for the type system. Turning it directly into a raw pointer would not be
// recognized as "releasing" the unique pointer to permit aliased raw accesses,
Expand All @@ -1064,8 +1100,9 @@ impl<T: ?Sized, A: Allocator> Box<T, A> {
/// to call it as `Box::allocator(&b)` instead of `b.allocator()`. This
/// is so that there is no conflict with a method on the inner type.
#[unstable(feature = "allocator_api", issue = "32838")]
#[rustc_const_unstable(feature = "const_box", issue = "92521")]
#[inline]
pub fn allocator(b: &Self) -> &A {
pub const fn allocator(b: &Self) -> &A {
&b.1
}

Expand Down Expand Up @@ -1105,8 +1142,9 @@ impl<T: ?Sized, A: Allocator> Box<T, A> {
/// assert_eq!(*static_ref, [4, 2, 3]);
/// ```
#[stable(feature = "box_leak", since = "1.26.0")]
#[rustc_const_unstable(feature = "const_box", issue = "92521")]
#[inline]
pub fn leak<'a>(b: Self) -> &'a mut T
pub const fn leak<'a>(b: Self) -> &'a mut T
oli-obk marked this conversation as resolved.
Show resolved Hide resolved
where
A: 'a,
{
Expand All @@ -1119,7 +1157,8 @@ impl<T: ?Sized, A: Allocator> Box<T, A> {
///
/// This is also available via [`From`].
#[unstable(feature = "box_into_pin", issue = "62370")]
pub fn into_pin(boxed: Self) -> Pin<Self>
#[rustc_const_unstable(feature = "const_box", issue = "92521")]
pub const fn into_pin(boxed: Self) -> Pin<Self>
where
A: 'static,
{
Expand All @@ -1131,7 +1170,8 @@ impl<T: ?Sized, A: Allocator> Box<T, A> {
}

#[stable(feature = "rust1", since = "1.0.0")]
unsafe impl<#[may_dangle] T: ?Sized, A: Allocator> Drop for Box<T, A> {
#[rustc_const_unstable(feature = "const_box", issue = "92521")]
unsafe impl<#[may_dangle] T: ?Sized, A: Allocator> const Drop for Box<T, A> {
fn drop(&mut self) {
// FIXME: Do nothing, drop is currently performed by compiler.
}
Expand Down Expand Up @@ -1341,7 +1381,8 @@ impl<T> From<T> for Box<T> {
}

#[stable(feature = "pin", since = "1.33.0")]
impl<T: ?Sized, A: Allocator> From<Box<T, A>> for Pin<Box<T, A>>
#[rustc_const_unstable(feature = "const_box", issue = "92521")]
impl<T: ?Sized, A: Allocator> const From<Box<T, A>> for Pin<Box<T, A>>
where
A: 'static,
{
Expand Down Expand Up @@ -1720,7 +1761,8 @@ impl<T: ?Sized, A: Allocator> fmt::Pointer for Box<T, A> {
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<T: ?Sized, A: Allocator> Deref for Box<T, A> {
#[rustc_const_unstable(feature = "const_box", issue = "92521")]
impl<T: ?Sized, A: Allocator> const Deref for Box<T, A> {
type Target = T;

fn deref(&self) -> &T {
Expand All @@ -1729,7 +1771,8 @@ impl<T: ?Sized, A: Allocator> Deref for Box<T, A> {
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<T: ?Sized, A: Allocator> DerefMut for Box<T, A> {
#[rustc_const_unstable(feature = "const_box", issue = "92521")]
impl<T: ?Sized, A: Allocator> const DerefMut for Box<T, A> {
fn deref_mut(&mut self) -> &mut T {
&mut **self
}
Expand Down Expand Up @@ -1908,7 +1951,8 @@ impl<T: ?Sized, A: Allocator> AsMut<T> for Box<T, A> {
* could have a method to project a Pin<T> from it.
*/
#[stable(feature = "pin", since = "1.33.0")]
impl<T: ?Sized, A: Allocator> Unpin for Box<T, A> where A: 'static {}
#[rustc_const_unstable(feature = "const_box", issue = "92521")]
impl<T: ?Sized, A: Allocator> const Unpin for Box<T, A> where A: 'static {}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is const Unpin supposed to mean?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It doesn't make sense to implement a marker trait as const, but I made it const with the intention of indicating that Box can be unpinned even at compile-time.


#[unstable(feature = "generator_trait", issue = "43122")]
impl<G: ?Sized + Generator<R> + Unpin, R, A: Allocator> Generator<R> for Box<G, A>
Expand Down
16 changes: 16 additions & 0 deletions library/alloc/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -96,9 +96,20 @@
#![feature(array_windows)]
#![feature(async_stream)]
#![feature(coerce_unsized)]
#![cfg_attr(not(no_global_oom_handling), feature(const_alloc_error))]
#![feature(const_box)]
#![cfg_attr(not(no_global_oom_handling), feature(const_btree_new))]
#![feature(const_cow_is_borrowed)]
#![feature(const_convert)]
#![feature(const_size_of_val)]
#![feature(const_align_of_val)]
#![feature(const_ptr_read)]
#![feature(const_maybe_uninit_write)]
#![feature(const_maybe_uninit_as_mut_ptr)]
#![feature(const_refs_to_cell)]
#![feature(core_intrinsics)]
#![feature(const_eval_select)]
#![feature(const_pin)]
#![feature(dispatch_from_dyn)]
#![feature(exact_size_is_empty)]
#![feature(extend_one)]
Expand Down Expand Up @@ -134,8 +145,13 @@
#![feature(box_syntax)]
#![feature(cfg_sanitize)]
#![feature(cfg_target_has_atomic)]
#![feature(const_deref)]
#![feature(const_fn_trait_bound)]
#![feature(const_mut_refs)]
#![feature(const_ptr_write)]
#![feature(const_precise_live_drops)]
#![feature(const_trait_impl)]
#![feature(const_try)]
#![cfg_attr(bootstrap, feature(destructuring_assignment))]
#![feature(dropck_eyepatch)]
#![feature(exclusive_range_pattern)]
Expand Down
Loading