//! A pointer type for heap allocation.
//!
-//! `Box<T>`, casually referred to as a 'box', provides the simplest form of
+//! [`Box<T>`], casually referred to as a 'box', provides the simplest form of
//! heap allocation in Rust. Boxes provide ownership for this allocation, and
//! drop their contents when they go out of scope.
//!
//! Nil,
//! }
//!
-//! fn main() {
-//! let list: List<i32> = List::Cons(1, Box::new(List::Cons(2, Box::new(List::Nil))));
-//! println!("{:?}", list);
-//! }
+//! let list: List<i32> = List::Cons(1, Box::new(List::Cons(2, Box::new(List::Nil))));
+//! println!("{:?}", list);
//! ```
//!
//! This will print `Cons(1, Cons(2, Nil))`.
//!
//! It wouldn't work. This is because the size of a `List` depends on how many
//! elements are in the list, and so we don't know how much memory to allocate
-//! for a `Cons`. By introducing a `Box`, which has a defined size, we know how
+//! for a `Cons`. By introducing a [`Box<T>`], which has a defined size, we know how
//! big `Cons` needs to be.
//!
//! # Memory layout
//! [`Layout`] used with the allocator is correct for the type. More precisely,
//! a `value: *mut T` that has been allocated with the [`Global`] allocator
//! with `Layout::for_value(&*value)` may be converted into a box using
-//! `Box::<T>::from_raw(value)`. Conversely, the memory backing a `value: *mut
-//! T` obtained from `Box::<T>::into_raw` may be deallocated using the
-//! [`Global`] allocator with `Layout::for_value(&*value)`.
+//! [`Box::<T>::from_raw(value)`]. Conversely, the memory backing a `value: *mut
+//! T` obtained from [`Box::<T>::into_raw`] may be deallocated using the
+//! [`Global`] allocator with [`Layout::for_value(&*value)`].
//!
-//! So long as `T: Sized`, a `Box<T>` is guaranteed to be represented as a
-//! single pointer and is also ABI-compatible with C pointers (i.e. the C type
-//! `T*`). This means that you have Rust code which passes ownership of a
-//! `Box<T>` to C code by using `Box<T>` as the type on the Rust side, and
-//! `T*` as the corresponding type on the C side. As an example, consider this
-//! C header which declares functions that create and destroy some kind of
-//! `Foo` value:
+//! So long as `T: Sized`, a `Box<T>` is guaranteed to be represented
+//! as a single pointer and is also ABI-compatible with C pointers
+//! (i.e. the C type `T*`). This means that if you have extern "C"
+//! Rust functions that will be called from C, you can define those
+//! Rust functions using `Box<T>` types, and use `T*` as corresponding
+//! type on the C side. As an example, consider this C header which
+//! declares functions that create and destroy some kind of `Foo`
+//! value:
//!
//! ```c
//! /* C header */
-//! struct Foo* foo_new(void); /* Returns ownership to the caller */
-//! void foo_delete(struct Foo*); /* Takes ownership from the caller */
+//!
+//! /* Returns ownership to the caller */
+//! struct Foo* foo_new(void);
+//!
+//! /* Takes ownership from the caller; no-op when invoked with NULL */
+//! void foo_delete(struct Foo*);
//! ```
-//!
+//!
//! These two functions might be implemented in Rust as follows. Here, the
//! `struct Foo*` type from C is translated to `Box<Foo>`, which captures
//! the ownership constraints. Note also that the nullable argument to
//! #[no_mangle]
//! pub extern "C" fn foo_delete(_: Option<Box<Foo>>) {}
//! ```
-//!
+//!
//! Even though `Box<T>` has the same representation and C ABI as a C pointer,
//! this does not mean that you can convert an arbitrary `T*` into a `Box<T>`
//! and expect things to work. `Box<T>` values will always be fully aligned,
//! is to only use `Box<T>` for pointers that originated from the global
//! allocator.
//!
+//! **Important.** At least at present, you should avoid using
+//! `Box<T>` types for functions that are defined in C but invoked
+//! from Rust. In those cases, you should directly mirror the C types
+//! as closely as possible. Using types like `Box<T>` where the C
+//! definition is just using `T*` can lead to undefined behavior, as
+//! described in [rust-lang/unsafe-code-guidelines#198][ucg#198].
+//!
+//! [ucg#198]: https://github.com/rust-lang/unsafe-code-guidelines/issues/198
//! [dereferencing]: ../../std/ops/trait.Deref.html
//! [`Box`]: struct.Box.html
+//! [`Box<T>`]: struct.Box.html
+//! [`Box::<T>::from_raw(value)`]: struct.Box.html#method.from_raw
+//! [`Box::<T>::into_raw`]: struct.Box.html#method.into_raw
//! [`Global`]: ../alloc/struct.Global.html
//! [`Layout`]: ../alloc/struct.Layout.html
+//! [`Layout::for_value(&*value)`]: ../alloc/struct.Layout.html#method.for_value
#![stable(feature = "rust1", since = "1.0.0")]
use core::any::Any;
+use core::array::LengthAtMost32;
use core::borrow;
use core::cmp::Ordering;
-use core::convert::From;
+use core::convert::{From, TryFrom};
use core::fmt;
use core::future::Future;
use core::hash::{Hash, Hasher};
-use core::iter::{Iterator, FromIterator, FusedIterator};
+use core::iter::{FromIterator, FusedIterator, Iterator};
use core::marker::{Unpin, Unsize};
use core::mem;
-use core::pin::Pin;
use core::ops::{
- CoerceUnsized, DispatchFromDyn, Deref, DerefMut, Receiver, Generator, GeneratorState
+ CoerceUnsized, Deref, DerefMut, DispatchFromDyn, Generator, GeneratorState, Receiver,
};
+use core::pin::Pin;
use core::ptr::{self, NonNull, Unique};
+use core::slice;
use core::task::{Context, Poll};
-use crate::vec::Vec;
+use crate::alloc::{self, Alloc, Global};
use crate::raw_vec::RawVec;
use crate::str::from_boxed_utf8_unchecked;
+use crate::vec::Vec;
/// A pointer type for heap allocation.
///
box x
}
+ /// Constructs a new box with uninitialized contents.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// #![feature(new_uninit)]
+ ///
+ /// let mut five = Box::<u32>::new_uninit();
+ ///
+ /// let five = unsafe {
+ /// // Deferred initialization:
+ /// five.as_mut_ptr().write(5);
+ ///
+ /// five.assume_init()
+ /// };
+ ///
+ /// assert_eq!(*five, 5)
+ /// ```
+ #[unstable(feature = "new_uninit", issue = "63291")]
+ pub fn new_uninit() -> Box<mem::MaybeUninit<T>> {
+ let layout = alloc::Layout::new::<mem::MaybeUninit<T>>();
+ if layout.size() == 0 {
+ return Box(NonNull::dangling().into());
+ }
+ let ptr =
+ unsafe { Global.alloc(layout).unwrap_or_else(|_| alloc::handle_alloc_error(layout)) };
+ Box(ptr.cast().into())
+ }
+
+ /// Constructs a new `Box` with uninitialized contents, with the memory
+ /// being filled with `0` bytes.
+ ///
+ /// See [`MaybeUninit::zeroed`][zeroed] for examples of correct and incorrect usage
+ /// of this method.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// #![feature(new_uninit)]
+ ///
+ /// let zero = Box::<u32>::new_zeroed();
+ /// let zero = unsafe { zero.assume_init() };
+ ///
+ /// assert_eq!(*zero, 0)
+ /// ```
+ ///
+ /// [zeroed]: ../../std/mem/union.MaybeUninit.html#method.zeroed
+ #[unstable(feature = "new_uninit", issue = "63291")]
+ pub fn new_zeroed() -> Box<mem::MaybeUninit<T>> {
+ unsafe {
+ let mut uninit = Self::new_uninit();
+ ptr::write_bytes::<T>(uninit.as_mut_ptr(), 0, 1);
+ uninit
+ }
+ }
+
/// Constructs a new `Pin<Box<T>>`. If `T` does not implement `Unpin`, then
/// `x` will be pinned in memory and unable to be moved.
#[stable(feature = "pin", since = "1.33.0")]
}
}
+impl<T> Box<[T]> {
+ /// Constructs a new boxed slice with uninitialized contents.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// #![feature(new_uninit)]
+ ///
+ /// let mut values = Box::<[u32]>::new_uninit_slice(3);
+ ///
+ /// let values = unsafe {
+ /// // Deferred initialization:
+ /// values[0].as_mut_ptr().write(1);
+ /// values[1].as_mut_ptr().write(2);
+ /// values[2].as_mut_ptr().write(3);
+ ///
+ /// values.assume_init()
+ /// };
+ ///
+ /// assert_eq!(*values, [1, 2, 3])
+ /// ```
+ #[unstable(feature = "new_uninit", issue = "63291")]
+ pub fn new_uninit_slice(len: usize) -> Box<[mem::MaybeUninit<T>]> {
+ let layout = alloc::Layout::array::<mem::MaybeUninit<T>>(len).unwrap();
+ let ptr = if layout.size() == 0 {
+ NonNull::dangling()
+ } else {
+ unsafe {
+ Global.alloc(layout).unwrap_or_else(|_| alloc::handle_alloc_error(layout)).cast()
+ }
+ };
+ let slice = unsafe { slice::from_raw_parts_mut(ptr.as_ptr(), len) };
+ Box(Unique::from(slice))
+ }
+}
+
+impl<T> Box<mem::MaybeUninit<T>> {
+ /// Converts to `Box<T>`.
+ ///
+ /// # Safety
+ ///
+ /// As with [`MaybeUninit::assume_init`],
+ /// it is up to the caller to guarantee that the value
+ /// really is in an initialized state.
+ /// Calling this when the content is not yet fully initialized
+ /// causes immediate undefined behavior.
+ ///
+ /// [`MaybeUninit::assume_init`]: ../../std/mem/union.MaybeUninit.html#method.assume_init
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// #![feature(new_uninit)]
+ ///
+ /// let mut five = Box::<u32>::new_uninit();
+ ///
+ /// let five: Box<u32> = unsafe {
+ /// // Deferred initialization:
+ /// five.as_mut_ptr().write(5);
+ ///
+ /// five.assume_init()
+ /// };
+ ///
+ /// assert_eq!(*five, 5)
+ /// ```
+ #[unstable(feature = "new_uninit", issue = "63291")]
+ #[inline]
+ pub unsafe fn assume_init(self) -> Box<T> {
+ Box(Box::into_unique(self).cast())
+ }
+}
+
+impl<T> Box<[mem::MaybeUninit<T>]> {
+ /// Converts to `Box<[T]>`.
+ ///
+ /// # Safety
+ ///
+ /// As with [`MaybeUninit::assume_init`],
+ /// it is up to the caller to guarantee that the values
+ /// really are in an initialized state.
+ /// Calling this when the content is not yet fully initialized
+ /// causes immediate undefined behavior.
+ ///
+ /// [`MaybeUninit::assume_init`]: ../../std/mem/union.MaybeUninit.html#method.assume_init
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// #![feature(new_uninit)]
+ ///
+ /// let mut values = Box::<[u32]>::new_uninit_slice(3);
+ ///
+ /// let values = unsafe {
+ /// // Deferred initialization:
+ /// values[0].as_mut_ptr().write(1);
+ /// values[1].as_mut_ptr().write(2);
+ /// values[2].as_mut_ptr().write(3);
+ ///
+ /// values.assume_init()
+ /// };
+ ///
+ /// assert_eq!(*values, [1, 2, 3])
+ /// ```
+ #[unstable(feature = "new_uninit", issue = "63291")]
+ #[inline]
+ pub unsafe fn assume_init(self) -> Box<[T]> {
+ Box(Unique::new_unchecked(Box::into_raw(self) as _))
+ }
+}
+
impl<T: ?Sized> Box<T> {
/// Constructs a box from a raw pointer.
///
/// ```
/// #![feature(box_into_raw_non_null)]
///
- /// fn main() {
- /// let x = Box::new(5);
- /// let ptr = Box::into_raw_non_null(x);
+ /// let x = Box::new(5);
+ /// let ptr = Box::into_raw_non_null(x);
///
- /// // Clean up the memory by converting the NonNull pointer back
- /// // into a Box and letting the Box be dropped.
- /// let x = unsafe { Box::from_raw(ptr.as_ptr()) };
- /// }
+ /// // Clean up the memory by converting the NonNull pointer back
+ /// // into a Box and letting the Box be dropped.
+ /// let x = unsafe { Box::from_raw(ptr.as_ptr()) };
/// ```
#[unstable(feature = "box_into_raw_non_null", issue = "47336")]
#[inline]
Box::into_unique(b).into()
}
- #[unstable(feature = "ptr_internals", issue = "0", reason = "use into_raw_non_null instead")]
+ #[unstable(feature = "ptr_internals", issue = "none", reason = "use into_raw_non_null instead")]
#[inline]
#[doc(hidden)]
pub fn into_unique(b: Box<T>) -> Unique<T> {
/// Simple usage:
///
/// ```
- /// fn main() {
- /// let x = Box::new(41);
- /// let static_ref: &'static mut usize = Box::leak(x);
- /// *static_ref += 1;
- /// assert_eq!(*static_ref, 42);
- /// }
+ /// let x = Box::new(41);
+ /// let static_ref: &'static mut usize = Box::leak(x);
+ /// *static_ref += 1;
+ /// assert_eq!(*static_ref, 42);
/// ```
///
/// Unsized data:
///
/// ```
- /// fn main() {
- /// let x = vec![1, 2, 3].into_boxed_slice();
- /// let static_ref = Box::leak(x);
- /// static_ref[0] = 4;
- /// assert_eq!(*static_ref, [4, 2, 3]);
- /// }
+ /// let x = vec![1, 2, 3].into_boxed_slice();
+ /// let static_ref = Box::leak(x);
+ /// static_ref[0] = 4;
+ /// assert_eq!(*static_ref, [4, 2, 3]);
/// ```
#[stable(feature = "box_leak", since = "1.26.0")]
#[inline]
pub fn leak<'a>(b: Box<T>) -> &'a mut T
where
- T: 'a // Technically not needed, but kept to be explicit.
+ T: 'a, // Technically not needed, but kept to be explicit.
{
unsafe { &mut *Box::into_raw(b) }
}
}
}
-
#[stable(feature = "box_slice_clone", since = "1.3.0")]
impl Clone for Box<str> {
fn clone(&self) -> Self {
// this makes a copy of the data
let buf: Box<[u8]> = self.as_bytes().into();
- unsafe {
- from_boxed_utf8_unchecked(buf)
- }
+ unsafe { from_boxed_utf8_unchecked(buf) }
}
}
}
}
+#[unstable(feature = "boxed_slice_try_from", issue = "none")]
+impl<T, const N: usize> TryFrom<Box<[T]>> for Box<[T; N]>
+where
+ [T; N]: LengthAtMost32,
+{
+ type Error = Box<[T]>;
+
+ fn try_from(boxed_slice: Box<[T]>) -> Result<Self, Self::Error> {
+ if boxed_slice.len() == N {
+ Ok(unsafe { Box::from_raw(Box::into_raw(boxed_slice) as *mut [T; N]) })
+ } else {
+ Err(boxed_slice)
+ }
+ }
+}
+
impl Box<dyn Any> {
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
/// }
/// }
///
- /// fn main() {
- /// let my_string = "Hello World".to_string();
- /// print_if_string(Box::new(my_string));
- /// print_if_string(Box::new(0i8));
- /// }
+ /// let my_string = "Hello World".to_string();
+ /// print_if_string(Box::new(my_string));
+ /// print_if_string(Box::new(0i8));
/// ```
pub fn downcast<T: Any>(self) -> Result<Box<T>, Box<dyn Any>> {
if self.is::<T>() {
/// }
/// }
///
- /// fn main() {
- /// let my_string = "Hello World".to_string();
- /// print_if_string(Box::new(my_string));
- /// print_if_string(Box::new(0i8));
- /// }
+ /// let my_string = "Hello World".to_string();
+ /// print_if_string(Box::new(my_string));
+ /// print_if_string(Box::new(0i8));
/// ```
pub fn downcast<T: Any>(self) -> Result<Box<T>, Box<dyn Any + Send>> {
<Box<dyn Any>>::downcast(self).map_err(|s| unsafe {
}
}
-#[unstable(feature = "receiver_trait", issue = "0")]
+#[unstable(feature = "receiver_trait", issue = "none")]
impl<T: ?Sized> Receiver for Box<T> {}
#[stable(feature = "rust1", since = "1.0.0")]
fn nth(&mut self, n: usize) -> Option<I::Item> {
(**self).nth(n)
}
+ fn last(self) -> Option<I::Item> {
+ BoxIter::last(self)
+ }
+}
+
+trait BoxIter {
+ type Item;
+ fn last(self) -> Option<Self::Item>;
+}
+
+impl<I: Iterator + ?Sized> BoxIter for Box<I> {
+ type Item = I::Item;
+ default fn last(self) -> Option<I::Item> {
+ #[inline]
+ fn some<T>(_: Option<T>, x: T) -> Option<T> {
+ Some(x)
+ }
+
+ self.fold(None, some)
+ }
}
+/// Specialization for sized `I`s that uses `I`s implementation of `last()`
+/// instead of the default.
#[stable(feature = "rust1", since = "1.0.0")]
-impl<I: Iterator + Sized> Iterator for Box<I> {
- fn last(self) -> Option<I::Item> where I: Sized {
+impl<I: Iterator> BoxIter for Box<I> {
+ fn last(self) -> Option<I::Item> {
(*self).last()
}
}
#[unstable(feature = "coerce_unsized", issue = "27732")]
impl<T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<Box<U>> for Box<T> {}
-#[unstable(feature = "dispatch_from_dyn", issue = "0")]
+#[unstable(feature = "dispatch_from_dyn", issue = "none")]
impl<T: ?Sized + Unsize<U>, U: ?Sized> DispatchFromDyn<Box<U>> for Box<T> {}
#[stable(feature = "boxed_slice_from_iter", since = "1.32.0")]
#[stable(feature = "box_slice_clone", since = "1.3.0")]
impl<T: Clone> Clone for Box<[T]> {
fn clone(&self) -> Self {
- let mut new = BoxBuilder {
- data: RawVec::with_capacity(self.len()),
- len: 0,
- };
-
- let mut target = new.data.ptr();
-
- for item in self.iter() {
- unsafe {
- ptr::write(target, item.clone());
- target = target.offset(1);
- };
-
- new.len += 1;
- }
-
- return unsafe { new.into_box() };
-
- // Helper type for responding to panics correctly.
- struct BoxBuilder<T> {
- data: RawVec<T>,
- len: usize,
- }
-
- impl<T> BoxBuilder<T> {
- unsafe fn into_box(self) -> Box<[T]> {
- let raw = ptr::read(&self.data);
- mem::forget(self);
- raw.into_box()
- }
- }
-
- impl<T> Drop for BoxBuilder<T> {
- fn drop(&mut self) {
- let mut data = self.data.ptr();
- let max = unsafe { data.add(self.len) };
-
- while data != max {
- unsafe {
- ptr::read(data);
- data = data.offset(1);
- }
- }
- }
- }
+ self.to_vec().into_boxed_slice()
}
}
* could have a method to project a Pin<T> from it.
*/
#[stable(feature = "pin", since = "1.33.0")]
-impl<T: ?Sized> Unpin for Box<T> { }
+impl<T: ?Sized> Unpin for Box<T> {}
#[unstable(feature = "generator_trait", issue = "43122")]
impl<G: ?Sized + Generator + Unpin> Generator for Box<G> {