From ed63d32651105e56afceb94cbb86f115db235825 Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Wed, 1 Apr 2015 10:11:46 -0400 Subject: [PATCH] Add (unstable) FnBox trait as a nicer replacement for `Thunk`. The doc comment includes a test that also shows how it can be used. --- src/liballoc/boxed.rs | 75 +++++++++++++++++++++++++++++++++++++++++++ src/libstd/lib.rs | 1 + 2 files changed, 76 insertions(+) diff --git a/src/liballoc/boxed.rs b/src/liballoc/boxed.rs index 550b25ac3a7..8d3a63ceb50 100644 --- a/src/liballoc/boxed.rs +++ b/src/liballoc/boxed.rs @@ -355,3 +355,78 @@ impl<'a, 'b> From<&'b str> for Box { } } } + +/// `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); +/// } +/// } +/// ``` +#[cfg(not(stage0))] +#[rustc_paren_sugar] +#[unstable(feature = "core", reason = "Newly introduced")] +pub trait FnBox { + type Output; + + extern "rust-call" fn call_box(self: Box, args: A) -> Self::Output; +} + +#[cfg(not(stage0))] +impl FnBox for F + where F: FnOnce +{ + type Output = F::Output; + + extern "rust-call" fn call_box(self: Box, args: A) -> F::Output { + self.call_once(args) + } +} + +#[cfg(not(stage0))] +impl FnOnce for Box> { + type Output = R; + + extern "rust-call" fn call_once(self, args: A) -> R { + self.call_box(args) + } +} + +#[cfg(not(stage0))] +impl FnOnce for Box+Send> { + type Output = R; + + extern "rust-call" fn call_once(self, args: A) -> R { + self.call_box(args) + } +} diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs index 41ac3d60df5..3c73ce7634c 100644 --- a/src/libstd/lib.rs +++ b/src/libstd/lib.rs @@ -243,6 +243,7 @@ mod uint_macros; #[path = "num/f64.rs"] pub mod f64; pub mod ascii; + pub mod thunk; /* Common traits */