Skip to content

Commit ed63d32

Browse files
committed
Add (unstable) FnBox trait as a nicer replacement for Thunk. The doc
comment includes a test that also shows how it can be used.
1 parent d528aa9 commit ed63d32

File tree

2 files changed

+76
-0
lines changed

2 files changed

+76
-0
lines changed

src/liballoc/boxed.rs

+75
Original file line numberDiff line numberDiff line change
@@ -355,3 +355,78 @@ impl<'a, 'b> From<&'b str> for Box<Error + Send + 'a> {
355355
}
356356
}
357357
}
358+
359+
/// `FnBox` is a version of the `FnOnce` intended for use with boxed
360+
/// closure objects. The idea is that where one would normally store a
361+
/// `Box<FnOnce()>` in a data structure, you should use
362+
/// `Box<FnBox()>`. The two traits behave essentially the same, except
363+
/// that a `FnBox` closure can only be called if it is boxed. (Note
364+
/// that `FnBox` may be deprecated in the future if `Box<FnOnce()>`
365+
/// closures become directly usable.)
366+
///
367+
/// ### Example
368+
///
369+
/// Here is a snippet of code which creates a hashmap full of boxed
370+
/// once closures and then removes them one by one, calling each
371+
/// closure as it is removed. Note that the type of the closures
372+
/// stored in the map is `Box<FnBox() -> i32>` and not `Box<FnOnce()
373+
/// -> i32>`.
374+
///
375+
/// ```
376+
/// #![feature(core)]
377+
///
378+
/// use std::boxed::FnBox;
379+
/// use std::collections::HashMap;
380+
///
381+
/// fn make_map() -> HashMap<i32, Box<FnBox() -> i32>> {
382+
/// let mut map: HashMap<i32, Box<FnBox() -> i32>> = HashMap::new();
383+
/// map.insert(1, Box::new(|| 22));
384+
/// map.insert(2, Box::new(|| 44));
385+
/// map
386+
/// }
387+
///
388+
/// fn main() {
389+
/// let mut map = make_map();
390+
/// for i in &[1, 2] {
391+
/// let f = map.remove(&i).unwrap();
392+
/// assert_eq!(f(), i * 22);
393+
/// }
394+
/// }
395+
/// ```
396+
#[cfg(not(stage0))]
397+
#[rustc_paren_sugar]
398+
#[unstable(feature = "core", reason = "Newly introduced")]
399+
pub trait FnBox<A> {
400+
type Output;
401+
402+
extern "rust-call" fn call_box(self: Box<Self>, args: A) -> Self::Output;
403+
}
404+
405+
#[cfg(not(stage0))]
406+
impl<A,F> FnBox<A> for F
407+
where F: FnOnce<A>
408+
{
409+
type Output = F::Output;
410+
411+
extern "rust-call" fn call_box(self: Box<F>, args: A) -> F::Output {
412+
self.call_once(args)
413+
}
414+
}
415+
416+
#[cfg(not(stage0))]
417+
impl<A,R> FnOnce<A> for Box<FnBox<A,Output=R>> {
418+
type Output = R;
419+
420+
extern "rust-call" fn call_once(self, args: A) -> R {
421+
self.call_box(args)
422+
}
423+
}
424+
425+
#[cfg(not(stage0))]
426+
impl<A,R> FnOnce<A> for Box<FnBox<A,Output=R>+Send> {
427+
type Output = R;
428+
429+
extern "rust-call" fn call_once(self, args: A) -> R {
430+
self.call_box(args)
431+
}
432+
}

src/libstd/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -243,6 +243,7 @@ mod uint_macros;
243243
#[path = "num/f64.rs"] pub mod f64;
244244

245245
pub mod ascii;
246+
246247
pub mod thunk;
247248

248249
/* Common traits */

0 commit comments

Comments
 (0)