类型不匹配,解决了通过引用接受参数的闭包 [英] Type mismatches resolving a closure that takes arguments by reference

查看:127
本文介绍了类型不匹配,解决了通过引用接受参数的闭包的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在尝试编译下面的Rust代码时遇到一对奇怪的错误.在寻找其他有类似问题的人时,我遇到了另一个错误(看似对立)组合的问题,但无法将解决方案推广到我的问题.

I'm encountering a strange pair of errors while trying to compile my Rust code below. In searching for others with similar problems, I came across another question with the same combination of (seemingly opposing) errors, but couldn't generalize the solution from there to my problem.

基本上,我似乎在Rust的所有权系统中缺少微妙之处.在尝试在此处编译(非常精简的)代码时:

Basically, I seem to be missing a subtlety in Rust's ownership system. In trying to compile the (very pared down) code here:

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`

(为方便起见,Rust Playground链接此代码.)

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

It seems to me that the function I'm supplying to fold should type-check properly... what am I missing here and how can I go about fixing it?

推荐答案

简短的版本是,如果以内联方式编写闭包或将其存储为变量,则可以推断出的生存期之间存在差异.内联编写闭包并删除所有无关的类型:

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?.

此外,我还必须从输入数组中提取first值-您不能返回对局部变量的引用.该方法不需要寿命参数.他们将被推断出来.

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.

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

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

与Rust相关的问题是#41078 .

The related Rust issue is #41078.

这篇关于类型不匹配,解决了通过引用接受参数的闭包的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆