解决通过引用获取参数的闭包的类型不匹配
Type mismatches resolving a closure that takes arguments by reference
我在尝试编译下面的 Rust 代码时遇到了一对奇怪的错误。在寻找其他有类似问题的人时,我遇到了 ,但无法将解决方案从那里推广到我的问题。
基本上,我似乎遗漏了 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
的函数应该正确地进行类型检查……我在这里遗漏了什么,我该如何修复它?
简短的版本是,如果闭包是内联编写的或存储为变量,则推断的生命周期之间存在差异。内联编写闭包并删除所有无关类型:
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
值——您不能 return 对局部变量的引用。该方法不需要生命周期参数;他们将被推断出来。
要真正获取要编译的代码,您需要提供有关 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。
我在尝试编译下面的 Rust 代码时遇到了一对奇怪的错误。在寻找其他有类似问题的人时,我遇到了
基本上,我似乎遗漏了 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
的函数应该正确地进行类型检查……我在这里遗漏了什么,我该如何修复它?
简短的版本是,如果闭包是内联编写的或存储为变量,则推断的生命周期之间存在差异。内联编写闭包并删除所有无关类型:
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
值——您不能 return 对局部变量的引用。该方法不需要生命周期参数;他们将被推断出来。
要真正获取要编译的代码,您需要提供有关 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。