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

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

问题描述

我在尝试编译下面的 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天全站免登陆