Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 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
2 changes: 2 additions & 0 deletions compiler/rustc_middle/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
//! This API is completely unstable and subject to change.

#![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
#![feature(allocator_api)]
#![feature(array_windows)]
#![feature(assert_matches)]
#![feature(backtrace)]
Expand All @@ -33,6 +34,7 @@
#![feature(discriminant_kind)]
#![feature(never_type)]
#![feature(extern_types)]
#![feature(new_uninit)]
#![feature(nll)]
#![feature(once_cell)]
#![feature(min_specialization)]
Expand Down
7 changes: 4 additions & 3 deletions compiler/rustc_middle/src/mir/interpret/allocation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -131,8 +131,7 @@ impl<Tag> Allocation<Tag> {
/// Try to create an Allocation of `size` bytes, failing if there is not enough memory
/// available to the compiler to do so.
pub fn uninit(size: Size, align: Align, panic_on_fail: bool) -> InterpResult<'static, Self> {
let mut bytes = Vec::new();
bytes.try_reserve(size.bytes_usize()).map_err(|_| {
let bytes = Box::<[u8]>::try_new_zeroed_slice(size.bytes_usize()).map_err(|_| {
// This results in an error that can happen non-deterministically, since the memory
// available to the compiler can change between runs. Normally queries are always
// deterministic. However, we can be non-determinstic here because all uses of const
Expand All @@ -146,7 +145,9 @@ impl<Tag> Allocation<Tag> {
});
InterpError::ResourceExhaustion(ResourceExhaustionInfo::MemoryExhausted)
})?;
bytes.resize(size.bytes_usize(), 0);
// SAFETY: This turns a Box<[MaybeUninit<u8>]> into a Vec<u8>. This is safe since the box
// was zero-allocated which is a valid value for u8.
let bytes = unsafe { bytes.assume_init().into_vec() };
Ok(Allocation {
bytes,
relocations: Relocations::new(),
Expand Down
32 changes: 32 additions & 0 deletions library/alloc/src/boxed.rs
Original file line number Diff line number Diff line change
Expand Up @@ -589,6 +589,38 @@ impl<T> Box<[T]> {
pub fn new_zeroed_slice(len: usize) -> Box<[mem::MaybeUninit<T>]> {
unsafe { RawVec::with_capacity_zeroed(len).into_box(len) }
}

/// Constructs a new boxed slice with uninitialized contents, with the memory
Copy link
Contributor

Choose a reason for hiding this comment

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

Saying 'uninitialized contents' sounds confusing when we also state that the memory is zeroed. I think it would be better to write out MaybeUninit<T>, to make it clear that the allocated memory is initialized.

Copy link
Member Author

Choose a reason for hiding this comment

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

I copied that from another _zeroed function, should I fix those too?

/// being filled with `0` bytes. Returns an error if the allocation fails
///
/// See [`MaybeUninit::zeroed`][zeroed] for examples of correct and incorrect usage
/// of this method.
///
/// # Examples
///
/// ```
/// #![feature(allocator_api, new_uninit)]
///
/// let values = Box::<[u32]>::try_new_zeroed_slice(3)?;
/// let values = unsafe { values.assume_init() };
///
/// assert_eq!(*values, [0, 0, 0]);
/// # Ok::<(), std::alloc::AllocError>(())
/// ```
///
/// [zeroed]: mem::MaybeUninit::zeroed
#[unstable(feature = "allocator_api", issue = "32838")]
#[inline]
pub fn try_new_zeroed_slice(len: usize) -> Result<Box<[mem::MaybeUninit<T>]>, AllocError> {
unsafe {
let layout = match Layout::array::<mem::MaybeUninit<T>>(len) {
Ok(l) => l,
Err(_) => return Err(AllocError),
};
let ptr = Global.allocate_zeroed(layout)?;
Ok(RawVec::from_raw_parts_in(ptr.as_mut_ptr() as *mut _, len, Global).into_box(len))
}
}
}

impl<T, A: Allocator> Box<[T], A> {
Expand Down