Closure "must outlive the static lifetime". How do I solve this?


#1

I’m quite confused by a problem with lifetimes.

I have a function, find_root, which finds a root by Newton’s Method. Its signature is:

type RealFn<N> where N: Float + Div + Sub + PartialOrd = Fn(N) -> N;
pub fn find_root<'a, N>(function: &'a RealFn<N>, derivative: &'a RealFn<N>, x0: &N, acceptable_err: &N, max_iterations: i32) -> Option<N> 
where N: Float + Div + Sub + PartialOrd

I then have a method for finding square roots:

fn inv_sqrt<N>(radicand: &N, x: N) -> N 
    where N: Float + PartialOrd + Sub + Mul + Div {
    x.powi(2) - *radicand
}

fn inv_sqrt_derivative<N>(x: N) -> N
    where N: Float + PartialOrd + Sub + Mul + Div + From<f64> {
    x * 2.0.into()
}

pub fn find_sqrt<'a, N>(radicand: &'a N, x0: &'a N, 
                        acceptable_err: &'a N, max_iterations: i32)
                        -> Option<N> 
                        where N: Float + Div + Sub + Mul + PartialOrd + From<f64> {
    let specific_inv_sqrt: &'a Fn(N) -> N= &move |x| {
        inv_sqrt(radicand, x)
    };
    find_root(&specific_inv_sqrt, &inv_sqrt_derivative, x0, acceptable_err, max_iterations)
}

This does not compile. I get this error:

   Compiling nrfind v0.1.1 (file:///home/leo/Projects/nrfind)
error[E0477]: the type `&'a std::ops::Fn(N) -> N + 'a` does not fulfill the required lifetime
  --> src/sqrt.rs:22:15
   |
22 |     find_root(&specific_inv_sqrt, &inv_sqrt_derivative, x0, acceptable_err, max_iterations)
   |               ^^^^^^^^^^^^^^^^^^
   |
   = note: type must outlive the static lifetime

error: aborting due to previous error

error: Could not compile `nrfind`.

To learn more, run the command again with --verbose.

Unfortunately, I’ve tried a lot of things (as you can see with my flailing type annotations) and I have looked at a number of resources, but I have absolutely no idea what is going on. Please help?


#2

It seems like you’re specifying a lot of lifetimes that aren’t necessary. Sometimes these problems go away when you leave it up to the compiler. One issue I see specifically is that you’re specifying the closure lifetime in find_sqrt. Another issue you’ll run into is that you can’t pass &inv_sqrt_derivative in place of a closure.

I adapted your example on the play pen and made it compile with many fewer lifetimes. Note that I replaced your generic parameter N with f64 since playpen doesn’t have the num crate.

https://is.gd/X7mCAa


#3

It was something to do with specifying my trait bounds in the RealFn type declaration; removing that worked like a charm. Thanks!