diff --git a/src/liballoc/boxed.rs b/src/liballoc/boxed.rs index b2789a535fe49..3b82844202b7e 100644 --- a/src/liballoc/boxed.rs +++ b/src/liballoc/boxed.rs @@ -6,6 +6,68 @@ //! //! # Examples //! +//! A pointer type for heap allocation. +//! +//! [`Box`], 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. +//! +//! # Examples +//! +//! Move a value from the stack to the heap by creating a [`Box`]: +//! +//! ``` +//! let val: u8 = 5; +//! let boxed: Box = Box::new(val); +//! ``` +//! +//! Move a value from a [`Box`] back to the stack by [dereferencing]: +//! +//! ``` +//! let boxed: Box = Box::new(5); +//! let val: u8 = *boxed; +//! ``` +//! +//! Creating a recursive data structure: +//! +//! ``` +//! #[derive(Debug)] +//! enum List { +//! Cons(T, Box>), +//! Nil, +//! } +//! +//! let list: List = List::Cons(1, Box::new(List::Cons(2, Box::new(List::Nil)))); +//! println!("{:?}", list); +//! ``` +//! +//! This will print `Cons(1, Cons(2, Nil))`. +//! +//! Recursive structures must be boxed, because if the definition of `Cons` +//! looked like this: +//! +//! ```compile_fail,E0072 +//! # enum List { +//! Cons(T, List), +//! # } +//! ``` +//! +//! 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 +//! big `Cons` needs to be. +//! +//! # Memory layout +//! +//! For non-zero-sized values, a [`Box`] will use the [`Global`] allocator for +//! its allocation. It is valid to convert both ways between a [`Box`] and a +//! raw pointer allocated with the [`Global`] allocator, given that the +//! [`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::::from_raw(value)`]. Conversely, the memory backing a `value: *mut +//! T` obtained from [`Box::::into_raw`] may be deallocated using the + //! Move a value from the stack to the heap by creating a [`Box`]: //! //! ``` @@ -95,6 +157,7 @@ use core::task::{Context, Poll}; use crate::alloc::{self, Global, Alloc}; use crate::vec::Vec; use crate::raw_vec::RawVec; +use crate::string::String; use crate::str::from_boxed_utf8_unchecked; /// A pointer type for heap allocation. @@ -1070,3 +1133,10 @@ impl Future for Box { F::poll(Pin::new(&mut *self), cx) } } + +#[stable(feature = "box_str_from_iter", since = "1.40.0")] +impl FromIterator for Box { + fn from_iter>(iter: I) -> Box { + String::from_iter(iter).into_boxed_str() + } +} diff --git a/src/liballoc/tests.rs b/src/liballoc/tests.rs index ed46ba8a1b938..831dc6db1dc8c 100644 --- a/src/liballoc/tests.rs +++ b/src/liballoc/tests.rs @@ -151,3 +151,12 @@ fn test_array_from_slice() { let a: Result, _> = r.clone().try_into(); assert!(a.is_err()); } + +#[test] +fn box_str_from_iter(){ + let iter = (0..100).map(|_|{'☺'}); + let string: Box = iter.collect(); + + assert_eq!(string.chars().count(), 100); + assert_eq!(string.chars().nth(5), Some('☺')); +}