Can somebody help me to rewrite this piece of code with new unboxed closures:
struct Builder;
pub fn build(rules: |params: &mut Builder|) -> Builder {
let mut builder = Builder::new();
rules(&mut builder);
builder
}
I tried to write like this, but I got a lifetime error:
pub fn build<F>(rules: F) -> Builder where F: FnOnce<(&mut Builder,), ()> {
let mut builder = Builder::new();
rules(&mut builder);
builder
}
valico/src/builder.rs:48:59: 48:71 error: missing lifetime specifier [E0106]
valico/src/builder.rs:48 pub fn build<F>(rules: F) -> Builder where F: FnOnce<(&mut Builder,), ()> {
^~~~~~~~~~~~
What lifetime I need to specify? Simplified example in the sandbox.
This requires higher rank trait bounds, specifically, higher rank lifetimes. The full unsugared syntax would be
F: for<'a> FnOnce<(&'a mut Builder,), ()>.Using a lifetime on the function can't work, e.g. if we had
This says that
buildworks with whatever lifetime the caller wishes (e.g. they could chose'b=='static), but this is invalid, because there is a specific concrete lifetime that needs to be the used: the lifetime of the&mut builderinside the function. UsingF: for<'a> ...in a bound says thatFworks with any lifetime'a, so the compiler sees that it is legal to substitute in the one of&mut builder.As I hinted above, that's the really ugly unsugared syntax. There's two successive ways this can be made much nicer. Firstly, the canonical way to use the closure traits is the
()sugar:for<'a> FnOnce(&'a mut Builder) -> (), or, like with the rest of Rust, the-> ()can be dropped:for<'a> FnOnce(&'a mut Builder). (NB. this is just sugar forFnOnce<...>, but only the sugared syntax will be stabilised for interacting with these traits at 1.0.)Then, the paren syntax has a little extra rule: it automatically inserts lifetimes that act like
for<'a>(specifically, it undergoes lifetime elision with any inserted lifetime placed into aforon the trait), so justF: FnOnce(&mut Builder)is equivalent toF: for<'a> FnOnce(&'a mut Builder), and it's the recommended version.Applying these fixes to your playpen example:
playpen