Give reference to FnMut?


#1

I want to pass reference to callback, and reference should be to variable that lifetime = run_handler execution lifetime, so I create such simplified example of my problem.

fn run_handler<F: FnMut(&i32)>(mut f: F) {
    let val = 17_i32;
    f(&val);
}


fn main() {
    let h1 = |v| println!("v: {}", v);
    run_handler(h1);
}

this code not compiled, and as I understand the problem that rust compiler
can not understand how lifetime of h1 and run_handler cooperates.
How should I tell about this to compiler?


#2

I’m not sure why, but if you explicitly annotate the reference in argument type of the closure it works:

let h1 = |v: &_| println!("v: {}", v);

#3

Similarly, putting a closure directly into an argument list can help improve type inference:

fn main() {
    run_handler(|v| println!("v: {}", v));
}

This is just a bit of an odd quirk about rust’s type inference. If you’re assigning literal closures in let statements like this then at some point you’ve probably also ran into the dreaded “error: the type of this value must be known in this context”, which can be worked around using similar methods:

let f = |vec| vec.len();
//            ^^^ error:  the type of this value must be known in this context
iter.map(f).collect()

// ok:
let f = |vec: Vec<_>| vec.len();
iter.map(f).collect()

// also ok:
iter.map(|vec| vec.len()).collect()

#4

Type inference around closures is somewhat brittle and can easily break if you don’t pass a closure directly to the function that’s going to use it.

The simplest way around this is to use a hint function to tell the compiler how the closure will be used:

fn run_handler<F: FnMut(&i32)>(mut f: F) {
    let val = 17_i32;
    f(&val);
}

fn handler<F: FnMut(&i32)>(f: F) -> F {
    f
}

fn main() {
    let h1 = handler(|v| println!("v: {}", v));
    run_handler(h1);
}

This lets you store the closure with the correct properties without having to immediately use it.