在Rust中,lambda表达式的生命周期是多久?

8
如果我有一个返回函数的函数:
fn<'r, T> ( p : T ) -> (&'r fn(&'r str) -> ~[(T,int)]) {
     return |s| ~[(p, 0)]
}

然而,这似乎不起作用,我得到了以下(有些自相矛盾的)错误提示:
playground.rs:10:8: 10:29 error: cannot infer an appropriate lifetime due to conflicting requirements
playground.rs:10         return |s| ~[(p, 0i)]
                         ^~~~~~~~~~~~~~~~~~~~~
playground.rs:9:70: 11:5 note: first, the lifetime cannot outlive the block at 9:70...
playground.rs:9     pub fn result<'r, T>( p : T ) -> (&'r fn(&'r str) -> ~[(T, int)] ){
playground.rs:10         return |s| ~[(p, 0i)]
playground.rs:11     }
playground.rs:10:8: 10:29 note: ...due to the following expression
playground.rs:10         return |s| ~[(p, 0i)]
                         ^~~~~~~~~~~~~~~~~~~~~
playground.rs:9:70: 11:5 note: but, the lifetime must be valid for the lifetime &'r  as defined on the block at 9:70...
playground.rs:9     pub fn result<'r, T>( p : T ) -> (&'r fn(&'r str) -> ~[(T, int)] ){
playground.rs:10         return |s| ~[(p, 0i)]
playground.rs:11     }
playground.rs:10:8: 10:29 note: ...due to the following expression
playground.rs:10         return |s| ~[(p, 0i)]
                         ^~~~~~~~~~~~~~~~~~~~~
error: aborting due to previous error

我认为这句话的意思是函数签名返回的生命周期与返回值的生命周期不匹配。但是,我不确定如何给 lambda 注释一个生命周期以使其工作。
1个回答

14
这是Rust中的一个常见错误,认为生命周期参数实际上影响生命周期。
事实并非如此,它们只允许编译器知道从函数返回的引用的持续时间。无论如何,这都是正确的,但现在编译器也知道了,可以更安全地允许更多代码。这是Rust仅进行局部分析(一次只查看一个函数)的结果。
在这种情况下,您正在创建一个堆栈闭包。顾名思义,堆栈闭包是在堆栈上创建的,然后将其返回到堆栈上。这类似于这个C代码:
int *foo() { int a = 5; return &a; }

很显然,返回时指向a的指针(或“引用”)将无效。这正是Rust要防止的。

在这种情况下,栈闭包的生命周期持续到函数结束,但生命周期参数要求它的生命周期比这更长(尽管没有明确说明需要多长),因此出现了不匹配的错误。

一个基本的经验法则是,如果您在函数上有生命周期参数,则需要在参数列表和返回类型中的每个参数位置上使用它,否则您可能做错了什么。

如果您真的希望返回闭包,则必须使用堆闭包~fn (&str) -> ~[(T, int)],因为它分配在堆上,可以更自由地传递(尽管仍然不能复制)。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接