首页 文章

类型不匹配解析一个通过引用获取参数的闭包

提问于
浏览
2

我在尝试编译下面的Rust代码时遇到了一对奇怪的错误 . 在搜索有类似问题的其他人时,我遇到了another question with the same combination of (seemingly opposing) errors,但无法将解决方案从那里推广到我的问题 .

基本上,我似乎在Rust的所有权系统中缺少一个微妙的东西 . 在这里尝试编译(非常削减)代码:

struct Point {
    x: f32,
    y: f32,
}

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

fn test<'a>(points: &'a [Point]) -> (&'a Point, f32) {
    let md = |(q, max_d): (&Point, f32), p: &'a Point| -> (&Point, f32) {
        let d = p.x + p.y; // Standing in for a function call
        if d > max_d {
            (p, d)
        } else {
            (q, max_d)
        }
    };

    fold(&points, (&Point { x: 0., y: 0. }, 0.), md)
}

我收到以下错误消息:

error[E0631]: type mismatch in closure arguments
  --> src/main.rs:23:5
   |
14 |     let md = |(q, max_d): (&Point, f32), p: &'a Point| -> (&Point, f32) {
   |              ---------------------------------------------------------- found signature of `for<'r> fn((&'r Point, f32), &'a Point) -> _`
...
23 |     fold(&points, (&Point { x: 0., y: 0. }, 0.), md)
   |     ^^^^ expected signature of `for<'r> fn((&Point, f32), &'r Point) -> _`
   |
   = note: required by `fold`

error[E0271]: type mismatch resolving `for<'r> <[closure@src/main.rs:14:14: 21:6] as std::ops::FnOnce<((&Point, f32), &'r Point)>>::Output == (&Point, f32)`
  --> src/main.rs:23:5
   |
23 |     fold(&points, (&Point { x: 0., y: 0. }, 0.), md)
   |     ^^^^ expected bound lifetime parameter, found concrete lifetime
   |
   = note: required by `fold`

(A Rust Playground link for this code, for convenience.)

在我看来,我正在提供给 fold 的功能应该正确地进行类型检查......我在这里缺少什么,我该如何解决它?

1 回答

  • 1

    简短版本是,如果闭包内联写入或存储为变量,则推断的生命周期之间存在差异 . 写内联闭包并删除所有无关的类型:

    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)
            }
        })
    }
    

    另外,我必须从输入数组中提取 first 值 - 你可以't return a reference to a local variable. There'不需要方法的生命周期参数;他们将被推断 .

    要实际获取要编译的代码,您需要提供有关 fold 方法的更多信息 . 具体来说,您必须指出传递给闭包的引用与传入的参数具有相同的生命周期 . 否则,它可能只是对局部变量的引用:

    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])
    }
    

    相关的Rust问题是#41078 .

相关问题