Type mismatches resolving a closure that takes arguments by reference

The short version is that there’s a difference between the lifetimes that are inferred if the closure is written inline or stored as a variable. Write the closure inline and remove all the extraneous types:

fn test(points: &[Point]) -> (&Point, f32) {
    let init = points.first().expect("No initial");
    fold(&points, (init, 0.), |(q, max_d), p| {
        let d = 12.;
        if d > max_d {
            (p, d)
        } else {
            (q, max_d)
        }
    })
}

If you truly must have the closure out-of-band, review How to declare a lifetime for a closure argument?.

Additionally, I had to pull the first value from the input array — you can’t return a reference to a local variable. There’s no need for lifetime parameters on the method; they will be inferred.

To actually get the code to compile, you need to provide more information about the fold method. Specifically, you have to indicate that the reference passed to the closure has the same lifetime as the argument passed in. Otherwise, it could just be a reference to a local variable:

fn fold<'a, S, T, F>(item: &'a [S], accum: T, f: F) -> T
where
    F: Fn(T, &'a S) -> T,
{
    f(accum, &item[0])
}

The related Rust issue is #41078.

Leave a Comment