How to rewrite code to new unboxed closures

白昼怎懂夜的黑 提交于 2019-12-05 02:48:10

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

pub fn build<'b, F>(rules: F) -> Builder where F: FnOnce<(&'b mut Builder,), ()>

This says that build works 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 builder inside the function. Using F: for<'a> ... in a bound says that F works 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 for FnOnce<...>, 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 a for on the trait), so just F: FnOnce(&mut Builder) is equivalent to F: for<'a> FnOnce(&'a mut Builder), and it's the recommended version.

Applying these fixes to your playpen example:

pub fn initialize_with_closure<F>(rules: F) -> uint where F: FnOnce(&mut uint) {
    let mut i = 0;
    rules(&mut i);

    i
}

// equivalently
pub fn initialize_with_closure_explicit<F>(rules: F) -> uint where F: for<'a> FnOnce(&'a mut uint) -> () {
    let mut i = 0;
    rules(&mut i);

    i
}

pub fn main() {
    initialize_with_closure(|i: &mut uint| *i = *i + 20);
    initialize_with_closure_explicit(|i: &mut uint| *i = *i + 20);
}

playpen

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!