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 以使其工作。

4

1 回答 1

13

所以这是rust中的一个常见错误,认为生命周期参数实际上会影响生命周期。

它们没有,它们只允许编译器知道从函数返回的引用持续了一定时间。无论如何这都是真的,但现在编译器也知道了,可以让更多的代码安全。这是 Rust 只进行局部分析的结果(一次只查看一个函数)。

在这种情况下,您正在创建一个堆栈闭包。顾名思义,堆栈闭包是在堆栈上创建的,然后您将其返回堆栈。这类似于此 C 代码:

int *foo() { int a = 5; return &a; }

显然,指向的指针(或“引用”)a在您返回时无效。这就是 Rust 所阻止的。

在这种情况下,堆栈闭包的生命周期在函数的持续时间内持续,但生命周期参数要求它持续更长的时间(尽管没有确切说明它到底有多长),因此会出现不匹配错误。

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

如果你真的想返回一个闭包,那么你必须使用一个堆闭包,~fn (&str) -> ~[(T, int)]因为它是在堆上分配的并且可以更自由地传递(尽管仍然没有被复制)。

于 2013-10-06T21:31:25.607 回答