Rust 为什么这个简单的闭包失败了,而其他两个函数成功了?

Rust 为什么这个简单的闭包失败了,而其他两个函数成功了?,rust,closures,Rust,Closures,我已经构建了一个闭包示例,我无法开始工作,也找不到任何不应该工作的原因。为什么它在最后一次闭包时无法编译 struct S{} fn过滤器(谓词:P) 哪里 P:Fn&S)->bool, { 谓词(&S{}); } fn main(){ //这很有效 过滤器(|u s|true); //这同样有效 fn cb1(s:&s)->bool{ 真的 } 滤波器(cb1); //但这不起作用 设cb2=| | u s | true; 滤波器(cb2); } 输出: error[E0631]:闭包参数

我已经构建了一个闭包示例,我无法开始工作,也找不到任何不应该工作的原因。为什么它在最后一次闭包时无法编译

struct S{}
fn过滤器

(谓词:P) 哪里 P:Fn&S)->bool, { 谓词(&S{}); } fn main(){ //这很有效 过滤器(|u s|true); //这同样有效 fn cb1(s:&s)->bool{ 真的 } 滤波器(cb1); //但这不起作用 设cb2=| | u s | true; 滤波器(cb2); }

输出:

error[E0631]:闭包参数中的类型不匹配
-->/tmp/closure.rs:19:5
|
18 |让cb2=| | U s |为真;
|------找到了'fn(41;)的签名-->_`
19 |过滤器(cb2);
|^^^^^^^预期的签名为` for_`
|
注:过滤器为必填项`
-->/tmp/closure.rs:3:1
|
3 | fn filter

(谓词:P),其中P:fn(&S)->bool, | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 错误[E0271]:类型不匹配解析` for>::输出==bool` -->/tmp/closure.rs:19:5 | 19 |过滤器(cb2); |^^^^^预期的绑定生存期参数,找到具体的生存期 | 注:过滤器为必填项` -->/tmp/closure.rs:3:1 | 3 | fn filter

(谓词:P),其中P:fn(&S)->bool, | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

从以下内容可以看出,解决方案似乎是更改:

fn filter<P>(predicate: P)
where
    P: Fn(&S) -> bool,
{
    predicate(&S {});
}
fn过滤器

(谓词:P) 哪里 P:Fn&S)->bool, { 谓词(&S{}); }

fn过滤器布尔值,
{
谓词(&S{});
}
虽然我不知道为什么。它似乎与内联指定闭包时的推断生存期有关,而与存储在变量中并在以后使用闭包时的推断生存期有关。但不清楚为什么
&s
需要
'a
生存期,而
&s
不是返回的结果。如果您理解这一点,请在评论中解释

虽然这个问题已经“解决”,但最初发布的精简失败案例实际上并没有帮助我解决真正的问题,因为我无法编辑遇到问题的代码源

当我试图将存储的回调传递到
filter\u条目
方法时,问题就出现了。解决方案是在
filter\u条目
签名中加入显式生命周期,如本文前面所述,但您只能在编辑第三方代码时这样做。不幸的是,我认为这个问题的答案是“不能将存储的闭包与
filter\u条目一起使用”

不幸的是,我认为这个问题的答案是“不能将存储的闭包与
filter\u条目一起使用”

可以应用来自的方法来实现这一目标。与该答案类似,我们可以定义一个泛型
constraint
函数,该函数要求类型具有满足
filter
所需的生存期界限。我们将函数应用于闭包,然后将其存储到。请注意,在调用
filter
(这是我的第一次尝试)时调用
constraint(cb)
不起作用,因为编译器在传递给
constraint
时无法推断闭包变量的类型,就像在传递给
filter
时一样

调用
constraint
在运行时没有任何效果,它只是引导编译器推断出
过滤器所需变量的生存期界限。这允许存储闭包并调用
过滤器
,而无需修改其签名:

fn constrain<F>(fun: F) -> F
where
    F: for<'a> Fn(&'a S) -> bool,
{
    fun
}

fn main() {
    let cb = constrain(|_s| true);
    filter(cb);
}
fn约束(fun:F)->F
哪里
F:对于布尔,
{
乐趣
}
fn main(){
设cb=constraint(| | s | true);
滤波器(cb);
}

您的问题似乎可以通过以下答案得到回答:。如果没有,请回答您的问题以解释差异。否则,我们可以将此问题标记为已回答。我认为您不会得到比中提供的更好的解释,即当闭包位于变量中时,Rust编译器(当前)根本没有足够的智能来执行适当的推断。我已经能够了解有关此问题的更多信息,在艾迪的帮助下。基本要点是,我无法理解为什么编译器会关心
&'a
的生命周期,而它既没有用作输出,也没有被闭包捕获。答案基本上是@user4815162342所说的,即编译器不够聪明,无法知道闭包没有在某处存储
&S
,因此它需要保证引用将比闭包更有效。“如何声明…”答案中的
约束
函数实际上也适用于这里!只需小心地将
constraint
应用于闭包文本,而不是稍后在
filter
调用站点(就像我第一次尝试的那样)。请参阅我的答案以获得一个可运行的示例。
fn filter<'a, P>(predicate: P)
where
    P: Fn(&'a S) -> bool,
{
    predicate(&S {});
}
fn constrain<F>(fun: F) -> F
where
    F: for<'a> Fn(&'a S) -> bool,
{
    fun
}

fn main() {
    let cb = constrain(|_s| true);
    filter(cb);
}