[英]Taking closures with explicit lifetimes as arguments in Rust
The closures section of Rust documentation has this example: Rust文档的闭包部分包含以下示例:
fn call_with_ref<'a, F>(some_closure: F) -> i32
where F: Fn(&'a i32) -> i32
{
let value = 0;
some_closure(&value)
}
This doesn't compile because, as the docs put it: 这不能编译,因为如文档所述:
When a function has an explicit lifetime parameter, that lifetime must be at least as long as the entire call to that function.
当一个函数具有一个明确的生命周期参数时,该生命周期必须至少与对该函数的整个调用一样长。 The borrow checker will complain that value doesn't live long enough, because it is only in scope after its declaration inside the function body.
借位检查器会抱怨value的寿命不足,因为value仅在函数体内声明后才在范围之内。
The error message being 错误消息是
error: `value` does not live long enough
--> <anon>:5:19
|
5 | some_closure(&value);
| ^^^^^ does not live long enough
...
8 | }
| - borrowed value only lives until here
I am having trouble understanding this. 我很难理解这一点。 What does it mean that value does not live long enough?
价值没有足够长的寿命意味着什么? From what I understand value lives through the entire call of the function.
据我了解,价值贯穿于整个函数的调用。 So, where does the "not living long enough" come from?
那么,“寿命不足”从何而来呢?
When a lifetime appears in the parameter list, that means the caller gets to decide. 当生存期出现在参数列表中时,这意味着调用者可以决定。 The lifetime it chooses can be as long as it likes, and possibly longer than the closure lives for, even
'static
. 它选择的寿命可以是它喜欢的寿命,甚至可能长于密封盖的寿命,甚至是
'static
寿命。
Here's a bad example which is prevented by this error: 这是一个错误的示例,此错误可以防止此错误:
fn call_with_ref<'a, F>(some_closure: F) -> i32
where F: FnMut(&'a i32) -> i32
{
let value = 0;
some_closure(&value)
}
fn main() {
let mut refstore: Option<&'static i32> = None;
call_with_ref(|r| {
refstore = Some(r);
*r
});
}
If this version of call_with_ref
were allowed to compile, it would allow storing a dangling reference to the local value
variable in a variable which lives for longer. 如果允许此版本的
call_with_ref
进行编译,则它将允许将对局部value
变量的悬挂引用存储在寿命更长的变量中。
Note I've changed the function to take an FnMut
closure for simplicity; 注意,为简单起见,我将函数更改为采用
FnMut
闭包。 it would be possible to have the same unsafety using Fn
and a RefCell
, but it would have made the example more complicated. 使用
Fn
和RefCell
可能会有同样的不RefCell
,但这会使示例更加复杂。
( Playground with "bad" line commented out ) ( 带有“坏”字样的游乐场已被注释掉 )
The closures section of the book then shows the for<'a>
syntax, which changes the meaning of the lifetime bound. 然后,本书的闭包部分显示了
for<'a>
语法,该语法更改了生存期绑定的含义。
Translating to English, the following: 英文翻译如下:
fn call_with_ref<'a, F>(some_closure: F) -> i32
where F: Fn(&'a i32) -> i32
means roughly "given a lifetime 'a
, and a callable which takes a reference to an i32
which is valid for 'a
, I'll return an i32
". 大致表示“给定生命周期
'a
,并且可调用对象引用了对'a
有效的i32
,我将返回i32
”。 This means that the lifetime is set by the caller of call_with_ref
and is fixed. 这意味着生存期由
call_with_ref
的调用者设置,并且是固定的。
In contrast, the following: 相反,以下内容:
fn call_with_ref<F>(some_closure: F) -> i32
where F: for<'a> Fn(&'a i32) -> i32
means "given a callable which can take a reference to an i32
of any lifetime, I'll return an i32
". 表示“给定一个
i32
任何生命周期的i32
的可调用对象,我将返回i32
”。 The difference is that the closure will accept any reference lifetime (which outlives the call of the closure). 区别在于,闭包将接受任何引用生存期(超过了闭包的调用)。
In the first case, the lifetime is a parameter to call_with_ref
, so must outlive that call; 在第一种情况下,生存期是
call_with_ref
的参数,因此必须比该调用有效。 but in the second case it's a parameter to the closure itself and only needs to outlive the call to the closure. 但在第二种情况下,它是闭包本身的参数,只需要延长对闭包的调用的时间即可。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.