英文:
Why do I get a "borrowed data escapes outside of method" error?
问题
我有一个名为 renderer
的变量,我必须在事件循环中进行编辑。问题是,在我的 App
结构体的 run
函数中,事件循环总是出现相同的 borrowed data escapes outside of method
错误。我如何修复这个问题,同时仍然能够在运行时调整 renderer
的值?我看到的所有解决方案都导致某种形式的复制被传递,这不是我所需要的。感谢帮助!
完整错误:
error[E0521]: borrowed data escapes outside of method
--> src/app.rs:54:9
|
50 | pub fn run(mut self, renderer: &mut Renderer) -> Result<(), pixels::Error> {
| -------- - let's call the lifetime of this reference `'1`
| |
| `renderer` is a reference that is only valid in the method body
...
54 | / self.event_loop.run(move |event, _, control_flow| {
55 | | if let Event::RedrawRequested(_) = event {
56 | |
57 | | let current_frame_time = Instant::now();
... |
84 | | }
85 | | });
| | ^
| | |
| |__________`renderer` escapes the method body here
| argument requires that `'1` must outlive `'static`
有关完整的、较长的代码,请查看我的 GitHub 存储库:https://github.com/KGL8/RayTracingPaper/tree/working_snapshot
App.rs 的简化版本:
pub struct App {
// ***
}
impl App {
pub fn new() -> Result<Self, pixels::Error> {
// ***
}
pub fn create_window(event_loop: &EventLoop<()>) -> Window {
// ***
}
pub fn run(mut self, renderer: &mut Renderer) -> Result<(), pixels::Error> {
let mut previous_frame_time = Instant::now();
self.event_loop.run(move |event, _, control_flow| {
if let Event::RedrawRequested(_) = event {
let current_frame_time = Instant::now();
let timestep = current_frame_time.duration_since(previous_frame_time).as_secs_f32();
previous_frame_time = current_frame_time;
renderer.on_update(timestep, &self.input);
if let Err(err) = renderer.render(&mut self.pixels) {
log_error("renderer.draw_frame", err);
*control_flow = ControlFlow::Exit;
return;
}
}
// ***
self.window.request_redraw();
}
});
}
}
英文:
I have a variable renderer
that I have to edit over an event loop. The issue is that I keep getting the same borrowed data escapes outside of method
error for the event loop in the run
function of my App
struct. How do I fix this with still being able to adjust the values of renderer
over runtime? All the solutions I've seen resulted in some form of copy being passed, which is not what I need. Thanks for the help!
Full error:
error[E0521]: borrowed data escapes outside of method
--> src/app.rs:54:9
|
50 | pub fn run(mut self, renderer: &mut Renderer) -> Result<(), pixels::Error> {
| -------- - let's call the lifetime of this reference `'1`
| |
| `renderer` is a reference that is only valid in the method body
...
54 | / self.event_loop.run(move |event, _, control_flow| {
55 | | if let Event::RedrawRequested(_) = event {
56 | |
57 | | let current_frame_time = Instant::now();
... |
84 | | }
85 | | });
| | ^
| | |
| |__________`renderer` escapes the method body here
| argument requires that `'1` must outlive `'static`
For the full, long code, here is my GitHub repo: https://github.com/KGL8/RayTracingPaper/tree/working_snapshot
Shortened version of my App.rs:
pub struct App {
// ***
}
impl App {
pub fn new() -> Result<Self, pixels::Error> {
// ***
}
pub fn create_window(event_loop: &EventLoop<()>) -> Window {
// ***
}
pub fn run(mut self, renderer: &mut Renderer) -> Result<(), pixels::Error> {
let mut previous_frame_time = Instant::now();
self.event_loop.run(move |event, _, control_flow| {
if let Event::RedrawRequested(_) = event {
let current_frame_time = Instant::now();
let timestep = current_frame_time.duration_since(previous_frame_time).as_secs_f32();
previous_frame_time = current_frame_time;
renderer.on_update(timestep, &self.input);
if let Err(err) = renderer.render(&mut self.pixels) {
log_error("renderer.draw_frame", err);
*control_flow = ControlFlow::Exit;
return;
}
}
// ***
self.window.request_redraw();
}
});
}
}
答案1
得分: 3
你正在将一个可变引用 renderer
传递给 event_loop.run
,而 event_loop.run
是一个具有 'static
生命周期的闭包。
让我们看看 EventLoop::run
的源代码:
pub fn run<F>(self, event_handler: F) -> !
where
F: 'static + FnMut(Event<'_, T>, [ ... ] ),
'static + FnMut
部分表示“此参数是一个具有静态生命周期的闭包”。稍微解释一下:
- 闭包类似于函数,但它与调用函数所需的所有其他变量一起“捆绑在一起”
'static
是一个特殊的生命周期约束,它告诉 Rust 我们的闭包不会借用任何具有非'static
生命周期的数据
由于事件循环希望无限调用 event_handler
,所以 event_handler
必须在程序运行时继续存在。你正确地使用了一个 move
闭包,这会导致你的闭包中引用的所有变量被捕获并移动到闭包中(这就是上面提到的“捆绑”)。但是,renderer
是有问题的,因为它是一个引用,所以我们无法将其移动到闭包中。
我们有一个必须在程序结束之前存在的闭包,但包含一个在程序结束时就会消失的引用!这就是编译器所说的 borrowed data escapes outside of method
的意思。
为了解决这个问题,我们需要向编译器承诺 renderer
将一直存在直到程序退出。最简单的方法是将其变为 'static
,
在 App::run()
中:
pub fn run(mut self, renderer: &'static mut Renderer)
然后,在实例化 Renderer
时,使用 lazy_static:
lazy_static! {
static ref RENDERER: Renderer = Renderer::new();
}
英文:
You are passing renderer
, which is a mutable reference, into event_loop.run
, which is closure with a 'static
lifetime.
Let's look at the source for EventLoop::run
pub fn run<F>(self, event_handler: F) -> !
where
F: 'static + FnMut(Event<'_, T>, [ ... ] ),
The 'static + FnMut
part means "this argument is a closure with a static lifetime". To break it down a bit:
- a closure is a lot like function, but it's "bundled together" with all other variables needed to call the function
'static
is a special lifetime bound, it tells rust our closure will not borrow any data with non-'static
lifetime
Since the event loop wants to call the event_handler
indefinitely, event_handler
has to continue to exist as long as the program is running.
You correctly used a move
closure, which causes all the variables referred to in your closure to be captured and moved into the closure (that's the "bundling" above). renderer
is problematic, because it's a reference, so we can't move it into the closure.
We have a closure that has to live until the program ends, yet includes a reference that will die as soon as the program ends! This is what the compiler means by borrowed data escapes outside of method
.
To solve this, we need to promise the compiler that renderer
will stick around until the program exits. Easiest way is to make it 'static
,
In App::run()
pub fn run(mut self, renderer: &'static mut Renderer)
then, when you instantiate Renderer
, use lazy_static:
lazy_static! {
static ref RENDERER: Renderer = Renderer::new();
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论