Search code examples
rustrust-cargo

type annotation requires static lifetime


I want to compute the integral of a function using this crate : https://docs.rs/reikna/latest/reikna/integral/fn.integrate.html

Things goes wrong when I want to dynamically generate the function I want to integrate.

use reikna::integral::*;
use reikna::func;

fn calc(i: f64) -> f64 {
    let f = func!(|x| i + x);
    return integrate(&f, 0.0, 100.0);
}


fn main() {
    let res = calc(50.0);
    println!("The result is: {}", res);
}

I get this error :

error[E0597]: `i` does not live long enough
 --> src/main.rs:5:23
  |
5 |     let f = func!(|x| i + x);
  |             ----------^-----
  |             |     |   |
  |             |     |   borrowed value does not live long enough
  |             |     value captured here
  |             type annotation requires that `i` is borrowed for `'static`
6 |     return integrate(&f, 0.0, 100.0);
7 | }
  |  - `i` dropped here while still borrowed

For more information about this error, try `rustc --explain E0597`.

I checked how this crate was implemented. This is a simpler code explaining what's happening internally :

pub use std::rc::Rc;
pub type Function = Rc<dyn Fn(f64) -> f64>;

#[macro_export]
macro_rules! func {
    ($e:expr) => (Rc::new($e) as Function);
}

fn print_3_next_numbers(i: f64) {
    let f = func!(|x| 1.0 + x);
    println!("The next +1 number is: {}", f(1.0));
    println!("The next +2 number is: {}", f(2.0));
    println!("The next +3 number is: {}", f(3.0));
}


fn main() {
    print_3_next_numbers(50.0);
}

How can I do this with rust ?


Solution

  • Type alias Function is Rc<dyn Fn(f64) -> f64>, which requires that wrapped function is 'static (does not capture any lifetimes). But the closure you have created captures i by reference. You can force the closure to take ownership of i and move it into the closure.

    fn calc(i: f64) -> f64 {
        let f = func!(move |x| i + x);
        return integrate(&f, 0.0, 100.0);
    }