Is it possible to specify a generic lifetime on FnMut
in Rust for a function like this?
fn f1<'a, FRet:'a + FnMut() -> ()>(v: &'a mut i32) -> FRet {
let mut fret = || {
let i = v;
println!("inside");
// lots of complicated logic on captured var
*i = 5;
};
return fret;
}
Right now I'm getting an error, that return is incompatible with FRet
.
Your code has several issues. One is that you cannot make the function that returns a closure have a generic return type. f1
being generic over FRet
means that the caller gets to choose the FRet
, and that obviously can't work when you're returning a closure you implement, and not something the caller can or should specify. This is why the compiler complains that FRet
is incompatible with what you're actually returning.
The way to return a closure is by either boxing it or using the impl Trait
return type that declares an unnamed type returned by the function:
fn f1(v: &mut i32) -> impl FnMut() {
let fret = || {
let i = v;
println!("inside");
// lots of complicated logic on captured var
*i = 5;
};
fret
}
The above still doesn't compile with the compiler complaining that the closure is FnOnce
rather than FnMut
. This is because &mut i32
is not Copy
, so let i = v
actually moves the reference out of v
which makes the closure callable only once. That can be fixed with a reborrow, i.e. changing let i = v
to let i = &mut *v
.
After that the compiler will complain that the lifetime of reference is not captured by the closure, and that you can fix that by adding + '_
. (This is equivalent to declaring a lifetime 'a
and declaring v: &'a mut i32
and impl FnMut() + 'a
.) With this change the code compiles:
fn f1(v: &mut i32) -> impl FnMut() + '_ {
let fret = || {
let i = &mut *v;
println!("inside");
// lots of complicated logic on captured var
*i = 5;
};
fret
}