diff options
| author | Matthias Krüger <matthias.krueger@famsik.de> | 2022-01-04 16:34:14 +0100 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2022-01-04 16:34:14 +0100 |
| commit | c7125ba0fa4e9abe826f004a023c0bf3678a8963 (patch) | |
| tree | 5e8f67865ea68ec8a9ca08deb3e81c91bab6894a /library/alloc/src/alloc.rs | |
| parent | 50a66b75dcfb69fd23b1dca441d756f31d0b483f (diff) | |
| parent | 51e4291f2b3c63e62a61855d162c7dd700fcb44b (diff) | |
Rollup merge of #91884 - woppopo:const_box, r=oli-obk
Constify `Box<T, A>` methods
Tracking issue: none yet
Most of the methods bounded on `~const`. `intrinsics::const_eval_select` is used for handling an allocation error.
<details><summary>Constified API</summary>
```rust
impl<T, A: Allocator> Box<T, A> {
pub const fn new_in(x: T, alloc: A) -> Self
where
A: ~const Allocator + ~const Drop;
pub const fn try_new_in(x: T, alloc: A) -> Result<Self, AllocError>
where
T: ~const Drop,
A: ~const Allocator + ~const Drop;
pub const fn new_uninit_in(alloc: A) -> Box<mem::MaybeUninit<T>, A>
where
A: ~const Allocator + ~const Drop;
pub const fn try_new_uninit_in(alloc: A) -> Result<Box<mem::MaybeUninit<T>, A>, AllocError>
where
A: ~const Allocator + ~const Drop;
pub const fn new_zeroed_in(alloc: A) -> Box<mem::MaybeUninit<T>, A>
where
A: ~const Allocator + ~const Drop;
pub const fn try_new_zeroed_in(alloc: A) -> Result<Box<mem::MaybeUninit<T>, A>, AllocError>
where
A: ~const Allocator + ~const Drop;
pub const fn pin_in(x: T, alloc: A) -> Pin<Self>
where
A: 'static,
A: 'static + ~const Allocator + ~const Drop,
pub const fn into_boxed_slice(boxed: Self) -> Box<[T], A>;
pub const fn into_inner(boxed: Self) -> T
where
Self: ~const Drop,
}
impl<T, A: Allocator> Box<MaybeUninit<T>, A> {
pub const unsafe fn assume_init(self) -> Box<T, A>;
pub const fn write(mut boxed: Self, value: T) -> Box<T, A>;
pub const unsafe fn from_raw_in(raw: *mut T, alloc: A) -> Self;
pub const fn into_raw_with_allocator(b: Self) -> (*mut T, A);
pub const fn into_unique(b: Self) -> (Unique<T>, A);
pub const fn allocator(b: &Self) -> &A;
pub const fn leak<'a>(b: Self) -> &'a mut T
where
A: 'a;
pub const fn into_pin(boxed: Self) -> Pin<Self>
where
A: 'static;
}
unsafe impl<#[may_dangle] T: ?Sized, A: Allocator> const Drop for Box<T, A>;
impl<T: ?Sized, A: Allocator> const From<Box<T, A>> for Pin<Box<T, A>>
where
A: 'static;
impl<T: ?Sized, A: Allocator> const Deref for Box<T, A>;
impl<T: ?Sized, A: Allocator> const DerefMut for Box<T, A>;
impl<T: ?Sized, A: Allocator> const Unpin for Box<T, A> where A: 'static;
```
</details>
<details><summary>Example</summary>
```rust
pub struct ConstAllocator;
unsafe impl const Allocator for ConstAllocator {
fn allocate(&self, layout: Layout) -> Result<NonNull<[u8]>, AllocError> {
unsafe {
let ptr = core::intrinsics::const_allocate(layout.size(), layout.align());
Ok(NonNull::new_unchecked(ptr as *mut [u8; 0] as *mut [u8]))
}
}
unsafe fn deallocate(&self, _ptr: NonNull<u8>, _layout: Layout) {
/* do nothing */
}
fn allocate_zeroed(&self, layout: Layout) -> Result<NonNull<[u8]>, AllocError> {
self.allocate(layout)
}
unsafe fn grow(
&self,
_ptr: NonNull<u8>,
_old_layout: Layout,
_new_layout: Layout,
) -> Result<NonNull<[u8]>, AllocError> {
unimplemented!()
}
unsafe fn grow_zeroed(
&self,
_ptr: NonNull<u8>,
_old_layout: Layout,
_new_layout: Layout,
) -> Result<NonNull<[u8]>, AllocError> {
unimplemented!()
}
unsafe fn shrink(
&self,
_ptr: NonNull<u8>,
_old_layout: Layout,
_new_layout: Layout,
) -> Result<NonNull<[u8]>, AllocError> {
unimplemented!()
}
fn by_ref(&self) -> &Self
where
Self: Sized,
{
self
}
}
#[test]
fn const_box() {
const VALUE: u32 = {
let mut boxed = Box::new_in(1u32, ConstAllocator);
assert!(*boxed == 1);
*boxed = 42;
assert!(*boxed == 42);
*boxed
};
assert!(VALUE == 42);
}
```
</details>
Diffstat (limited to 'library/alloc/src/alloc.rs')
| -rw-r--r-- | library/alloc/src/alloc.rs | 23 |
1 files changed, 18 insertions, 5 deletions
diff --git a/library/alloc/src/alloc.rs b/library/alloc/src/alloc.rs index 66ef92558d8..d075658f51a 100644 --- a/library/alloc/src/alloc.rs +++ b/library/alloc/src/alloc.rs @@ -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) } } @@ -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. |
