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

implement FromIterator<char> for Box<str> #65168

Closed
wants to merge 12 commits into from
70 changes: 70 additions & 0 deletions src/liballoc/boxed.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,68 @@
//!
//! # Examples
//!
//! A pointer type for heap allocation.
Copy link
Contributor

Choose a reason for hiding this comment

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

It looks like our docs might still be a little confused here, because they've changed on master since you fixed them up.

Would you like to try squashing your 12 commits down and rebase on master?

//!
//! [`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.
//!
//! # Examples
//!
//! Move a value from the stack to the heap by creating a [`Box`]:
//!
//! ```
//! let val: u8 = 5;
//! let boxed: Box<u8> = Box::new(val);
//! ```
//!
//! Move a value from a [`Box`] back to the stack by [dereferencing]:
//!
//! ```
//! let boxed: Box<u8> = Box::new(5);
//! let val: u8 = *boxed;
//! ```
//!
//! Creating a recursive data structure:
//!
//! ```
//! #[derive(Debug)]
//! enum List<T> {
//! Cons(T, Box<List<T>>),
//! Nil,
//! }
//!
//! 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))`.
//!
//! Recursive structures must be boxed, because if the definition of `Cons`
//! looked like this:
//!
//! ```compile_fail,E0072
//! # enum List<T> {
//! Cons(T, List<T>),
//! # }
//! ```
//!
//! 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<T>`], 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::<T>::from_raw(value)`]. Conversely, the memory backing a `value: *mut
//! T` obtained from [`Box::<T>::into_raw`] may be deallocated using the

//! Move a value from the stack to the heap by creating a [`Box`]:
//!
//! ```
Expand Down Expand Up @@ -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.
Expand Down Expand Up @@ -1070,3 +1133,10 @@ impl<F: ?Sized + Future + Unpin> Future for Box<F> {
F::poll(Pin::new(&mut *self), cx)
}
}

#[stable(feature = "box_str_from_iter", since = "1.40.0")]
impl FromIterator<char> for Box<str> {
fn from_iter<I: IntoIterator<Item = char>>(iter: I) -> Box<str> {
String::from_iter(iter).into_boxed_str()
}
}
9 changes: 9 additions & 0 deletions src/liballoc/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -151,3 +151,12 @@ fn test_array_from_slice() {
let a: Result<Box<[u32; 2]>, _> = r.clone().try_into();
assert!(a.is_err());
}

#[test]
fn box_str_from_iter(){
let iter = (0..100).map(|_|{'☺'});
Copy link
Contributor

Choose a reason for hiding this comment

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

let string: Box<str> = iter.collect();

assert_eq!(string.chars().count(), 100);
assert_eq!(string.chars().nth(5), Some('☺'));
}