X-Git-Url: https://git.lizzy.rs/?a=blobdiff_plain;f=src%2Fliballoc%2Fboxed.rs;h=2801cf38cb75529d94912551a60a5eab51597235;hb=82dcec7ee4a8a71fdfb8e8771ae6785261ec1d5b;hp=550b25ac3a7cfa00e95ecee31063edf59cd8cf46;hpb=1d5ef755dee85001b88b696024eaa5a45a014dc3;p=rust.git diff --git a/src/liballoc/boxed.rs b/src/liballoc/boxed.rs index 550b25ac3a7..2801cf38cb7 100644 --- a/src/liballoc/boxed.rs +++ b/src/liballoc/boxed.rs @@ -51,15 +51,12 @@ use core::any::Any; use core::cmp::Ordering; use core::default::Default; -use core::error::Error; use core::fmt; use core::hash::{self, Hash}; use core::mem; use core::ops::{Deref, DerefMut}; -use core::ptr::{self, Unique}; -use core::raw::{TraitObject, Slice}; - -use heap; +use core::ptr::{Unique}; +use core::raw::{TraitObject}; /// A value that represents the heap. This is the default place that the `box` /// keyword allocates into when no place is supplied. @@ -86,6 +83,7 @@ /// See the [module-level documentation](../../std/boxed/index.html) for more. #[lang = "owned_box"] #[stable(feature = "rust1", since = "1.0.0")] +#[fundamental] pub struct Box(Unique); impl Box { @@ -277,13 +275,6 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { } } -#[stable(feature = "rust1", since = "1.0.0")] -impl fmt::Debug for Box { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - f.pad("Box") - } -} - #[stable(feature = "rust1", since = "1.0.0")] impl Deref for Box { type Target = T; @@ -309,49 +300,74 @@ fn next_back(&mut self) -> Option { (**self).next_back() } #[stable(feature = "rust1", since = "1.0.0")] impl ExactSizeIterator for Box {} -#[stable(feature = "rust1", since = "1.0.0")] -impl<'a, E: Error + 'a> From for Box { - fn from(err: E) -> Box { - Box::new(err) + +/// `FnBox` is a version of the `FnOnce` intended for use with boxed +/// closure objects. The idea is that where one would normally store a +/// `Box` in a data structure, you should use +/// `Box`. The two traits behave essentially the same, except +/// that a `FnBox` closure can only be called if it is boxed. (Note +/// that `FnBox` may be deprecated in the future if `Box` +/// closures become directly usable.) +/// +/// ### Example +/// +/// Here is a snippet of code which creates a hashmap full of boxed +/// once closures and then removes them one by one, calling each +/// closure as it is removed. Note that the type of the closures +/// stored in the map is `Box i32>` and not `Box i32>`. +/// +/// ``` +/// #![feature(core)] +/// +/// use std::boxed::FnBox; +/// use std::collections::HashMap; +/// +/// fn make_map() -> HashMap i32>> { +/// let mut map: HashMap i32>> = HashMap::new(); +/// map.insert(1, Box::new(|| 22)); +/// map.insert(2, Box::new(|| 44)); +/// map +/// } +/// +/// fn main() { +/// let mut map = make_map(); +/// for i in &[1, 2] { +/// let f = map.remove(&i).unwrap(); +/// assert_eq!(f(), i * 22); +/// } +/// } +/// ``` +#[rustc_paren_sugar] +#[unstable(feature = "core", reason = "Newly introduced")] +pub trait FnBox { + type Output; + + fn call_box(self: Box, args: A) -> Self::Output; +} + +impl FnBox for F + where F: FnOnce +{ + type Output = F::Output; + + fn call_box(self: Box, args: A) -> F::Output { + self.call_once(args) } } -#[stable(feature = "rust1", since = "1.0.0")] -impl<'a, E: Error + Send + 'a> From for Box { - fn from(err: E) -> Box { - Box::new(err) +impl<'a,A,R> FnOnce for Box+'a> { + type Output = R; + + extern "rust-call" fn call_once(self, args: A) -> R { + self.call_box(args) } } -#[stable(feature = "rust1", since = "1.0.0")] -impl<'a, 'b> From<&'b str> for Box { - fn from(err: &'b str) -> Box { - #[derive(Debug)] - struct StringError(Box); - impl Error for StringError { - fn description(&self) -> &str { &self.0 } - } - impl fmt::Display for StringError { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - self.0.fmt(f) - } - } +impl<'a,A,R> FnOnce for Box+Send+'a> { + type Output = R; - // Unfortunately `String` is located in libcollections, so we construct - // a `Box` manually here. - unsafe { - let alloc = if err.len() == 0 { - 0 as *mut u8 - } else { - let ptr = heap::allocate(err.len(), 1); - if ptr.is_null() { ::oom(); } - ptr as *mut u8 - }; - ptr::copy(err.as_bytes().as_ptr(), alloc, err.len()); - Box::new(StringError(mem::transmute(Slice { - data: alloc, - len: err.len(), - }))) - } + extern "rust-call" fn call_once(self, args: A) -> R { + self.call_box(args) } }