“错误:闭包可能会超过当前函数的寿命"但它不会比它长寿 [英] "error: closure may outlive the current function" but it will not outlive it
问题描述
当我尝试编译以下代码时:
When I try to compile the following code:
fn main() {
(...)
let mut should_end = false;
let mut input = Input::new(ctx);
input.add_handler(Box::new(|evt| {
match evt {
&Event::Quit{..} => {
should_end = true;
}
_ => {}
}
}));
while !should_end {
input.handle();
}
}
pub struct Input {
handlers: Vec<Box<FnMut(i32)>>,
}
impl Input {
pub fn new() -> Self {
Input {handlers: Vec::new()}
}
pub fn handle(&mut self) {
for a in vec![21,0,3,12,1] {
for handler in &mut self.handlers {
handler(a);
}
}
}
pub fn add_handler(&mut self, handler: Box<FnMut(i32)>) {
self.handlers.push(handler);
}
}
我收到此错误:
error: closure may outlive the current function, but it borrows `should_end`, which is owned by the current function
我不能简单地将move
添加到闭包中,因为稍后需要在主循环中使用should_end
.我的意思是,我可以,但是由于bool
是Copy
,它只会影响闭包内部的should_end
,因此程序会永远循环.
I can't simply add move
to the closure, because I need to use should_end
later in the main loop. I mean, I can, but since bool
is Copy
, it will only affect the should_end
inside the closure, and thus the program loops forever.
据我了解,由于input
是在主函数中创建的,而闭包存储在input
中,因此它不可能超过当前函数.有没有办法向Rust表示闭包不会超过main
?还是有可能我看不到闭包的寿命超过了main
?在后一种情况下,有一种方法可以强制它仅生存到main
?
As far as I understand, since input
is created in the main function, and the closure is stored in input
, it couldn't possibly outlive the current function. Is there a way to express to Rust that the closure won't outlive main
? Or is there a possibility that I can't see that the closure will outlive main
? In the latter case, it there a way to force it to live only as long as main
?
我是否需要重构我处理输入的方式,或者是否可以通过某种方式来完成这项工作.如果需要重构,在哪里可以找到Rust的一个很好的例子?
Do I need to refactor the way I'm handling input, or is there some way I can make this work. If I need to refactor, where can I look to see a good example of this in Rust?
这是简化版本的游戏围栏.我可能在其中犯了一个错误,可能会导致浏览器崩溃.我曾经碰巧遇到过一次,所以要当心.
Here's a playpen of a simplified version. It is possible I made a mistake in it that could crash your browser. I happened to me once, so, beware.
如果需要,我的代码可用.所有相关信息都应位于main.rs
或input.rs
中.
In case it is needed, the rest of my code is available. All the relevant info should be in either main.rs
or input.rs
.
推荐答案
问题不是您的关闭,而是add_handler
方法.完全扩展后,它看起来像这样:
The problem is not your closure, but the add_handler
method. Fully expanded it would look like this:
fn add_handler<'a>(&'a mut self, handler: Box<FnMut(i32) + 'static>)
如您所见,特征对象上绑定了一个隐式'static
.显然我们不想要这样,所以我们引入了第二个生命周期'b
:
As you can see, there's an implicit 'static
bound on the trait object. Obviously we don't want that, so we introduce a second lifetime 'b
:
fn add_handler<'a, 'b: 'a>(&'a mut self, handler: Box<FnMut(i32) + 'b>)
由于要将handler
对象添加到Input::handlers
字段,因此该字段不能超过handler
对象的范围.因此,我们还需要限制其寿命:
Since you are adding the handler
object to the Input::handlers
field, that field cannot outlive the scope of the handler
object. Thus we also need to limit its lifetime:
pub struct Input<'a> {
handlers: Vec<Box<FnMut(i32) + 'a>>,
}
这再次要求impl具有生存期,我们可以在add_handler
方法中使用它.
This again requires the impl to have a lifetime, which we can use in the add_handler
method.
impl<'a> Input<'a> {
...
pub fn add_handler(&mut self, handler: Box<FnMut(i32) + 'a>) {
self.handlers.push(handler);
}
}
现在剩下的就是使用Cell
来控制对should_end
标志的访问.
Now all that's left is using a Cell
to control access to your should_end
flag.
这篇关于“错误:闭包可能会超过当前函数的寿命"但它不会比它长寿的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!