Your code is using "boxed" closures. Those closures capture values by reference, so the captured value must live longer than the closure. You're trying to capture b, which is a parameter, so its lifetime is the duration of the function call. You cannot do what you want to do with "boxed closures.
Unboxed closures were added to the language to solve issues like this. Here's how map_one would be defined:
#![feature(overloaded_calls, unboxed_closures, unboxed_closure_sugar)] type Time = f32; fn map_one<'a, T, R, F: Fn<(T,), R>, B: Fn<(Time,), T>>( f: F, b: B) -> Box<Fn<(Time,), R>+'a> { box |&: time| -> R { f(b(time)) } }
Fn is a trait with a call method that takes self by immutable reference (FnMut takes self by mutable reference and FnOnce takes self by value). The captured values are moved into the closure, rather than referenced.
The input closure parameters are defined with a type parameter that implements the Fn trait, which is the only way to pass closures by value. The return value, however, must be boxed, because the concrete result type (which implements Fn) is created by the compiler, and we can't name it.
I tried writing a main that uses map_one, but I'm getting an internal compiler error... At that point, I can't tell if I made a mistake or if the code is supposed to be valid. (These Rust issues may be related to this error: #16672, #16791, #17060.)
fn main() { let t = 30f32; let fa = |&: a: String| -> uint { a.len() }; let fb = |&: b: f32| -> String { b.to_string() }; let m = map_one(fa, fb); let r = m.call((t,)); println!("{}", r); }
Note: I couldn't use your Behaviour generic type alias to bound B.
#![feature(overloaded_calls, unboxed_closures, unboxed_closure_sugar)] type Time = f32; type Behaviour<T> = Fn<(Time,), T>; fn map_one<'a, T, R, F: Fn<(T,), R>, B: Behaviour<T>>( f: F, b: B) -> Box<Behaviour<R>+'a> { box |&: time| -> R { f(b(time)) } }
The compiler complains:
<anon>:6:41: 6:53 error: `Behaviour` is not a trait <anon>:6 fn map_one<'a, T, R, F: Fn<(T,), R>, B: Behaviour<T>>( ^~~~~~~~~~~~ <anon>:6:41: 6:53 note: `type` aliases cannot be used for traits <anon>:6 fn map_one<'a, T, R, F: Fn<(T,), R>, B: Behaviour<T>>( ^~~~~~~~~~~~