为什么 Rust 似乎忽略了我的生命周期注解?
Why does Rust seem to ignore my lifetime annotation?
我有以下class
pub struct RectangleNode {
...
uniform_bind_group: wgpu::BindGroup,
...
}
应该实现以下特征
pub trait Node<'a, 'b> where 'a : 'b {
fn render(&'a self, render_pass: &'b mut wgpu::RenderPass);
}
我正在尝试按如下方式进行
impl<'a, 'b> node::Node<'a, 'b> for RectangleNode where 'a : 'b {
fn render(&'a self, render_pass: &'b mut wgpu::RenderPass) {
...
render_pass.set_bind_group(0, &self.uniform_bind_group, &[]);
...
}
}
这(显然?)给了我以下生命周期错误
error[E0495]: cannot infer an appropriate lifetime for borrow expression due to conflicting requirements
--> src/rectangle_node.rs:153:39
|
153 | render_pass.set_bind_group(0, &self.uniform_bind_group, &[]);
| ^^^^^^^^^^^^^^^^^^^^^^^^
|
note: first, the lifetime cannot outlive the lifetime `'a` as defined on the impl at 148:6...
--> src/rectangle_node.rs:148:6
|
148 | impl<'a, 'b> node::Node<'a, 'b> for RectangleNode where 'a : 'b {
| ^^
note: ...so that reference does not outlive borrowed content
--> src/rectangle_node.rs:153:39
|
153 | render_pass.set_bind_group(0, &self.uniform_bind_group, &[]);
| ^^^^^^^^^^^^^^^^^^^^^^^^
note: but, the lifetime must be valid for the anonymous lifetime #1 defined on the method body at 149:5...
--> src/rectangle_node.rs:149:5
|
149 | fn render(&'a self, render_pass: &'b mut wgpu::RenderPass) {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
note: ...so that the types are compatible
--> src/rectangle_node.rs:153:21
|
153 | render_pass.set_bind_group(0, &self.uniform_bind_group, &[]);
| ^^^^^^^^^^^^^^
= note: expected `&mut RenderPass<'_>`
found `&mut RenderPass<'_>`
但我很难理解问题所在。我试图声明 RectangleNode 的生命周期应该比 RenderPass 更长,因为我认为问题是 Rust 需要确保情况如此,但它似乎忽略了我在 RenderPass 上的生命周期注释并假设了一个匿名生命周期为了它?
编辑:
我可以通过更改为
来解决原来的问题
impl<'a, 'b> node::Node<'a, 'b> for RectangleNode where 'a : 'b {
fn render(&'a self, render_pass: &mut wgpu::RenderPass<'b>) {
...
render_pass.set_bind_group(0, &self.uniform_bind_group, &[]);
...
}
}
但这现在导致了另一个问题,我尝试使用以下代码
impl<'a, 'b> RenderArea where 'a : 'b {
pub fn render(&mut self, node: &'a dyn Node<'a, 'b>) -> Result<(), wgpu::SwapChainError> {
let frame = self.swap_chain.get_current_frame()?.output;
let mut encoder = self
.device
.create_command_encoder(&wgpu::CommandEncoderDescriptor {
label: Some("Render Encoder"),
});
let mut render_pass = encoder.begin_render_pass(&wgpu::RenderPassDescriptor {
color_attachments: &[wgpu::RenderPassColorAttachmentDescriptor {
attachment: &frame.view,
resolve_target: None,
ops: wgpu::Operations {
load: wgpu::LoadOp::Clear(self.bg_color),
store: true,
},
}],
depth_stencil_attachment: None,
});
node.render(&mut render_pass);
drop(render_pass);
self.queue.submit(std::iter::once(encoder.finish()));
Ok(())
}
}
然后给出以下错误
error[E0597]: `encoder` does not live long enough
--> src/render_area.rs:107:31
|
96 | impl<'a, 'b> RenderArea where 'a : 'b {
| -- lifetime `'b` defined here
...
107 | let mut render_pass = encoder.begin_render_pass(&wgpu::RenderPassDescriptor {
| -^^^^^^
| |
| _______________________________borrowed value does not live long enough
| |
108 | | color_attachments: &[wgpu::RenderPassColorAttachmentDescriptor {
109 | | attachment: &frame.view,
110 | | resolve_target: None,
... |
116 | | depth_stencil_attachment: None,
117 | | });
| |__________- assignment requires that `encoder` is borrowed for `'b`
...
124 | }
| - `encoder` dropped here while still borrowed
error[E0713]: borrow may still be in use when destructor runs
--> src/render_area.rs:109:29
|
96 | impl<'a, 'b> RenderArea where 'a : 'b {
| -- lifetime `'b` defined here
...
107 | let mut render_pass = encoder.begin_render_pass(&wgpu::RenderPassDescriptor {
| _______________________________-
108 | | color_attachments: &[wgpu::RenderPassColorAttachmentDescriptor {
109 | | attachment: &frame.view,
| | ^^^^^^^^^^^
110 | | resolve_target: None,
... |
116 | | depth_stencil_attachment: None,
117 | | });
| |__________- assignment requires that `frame.view` is borrowed for `'b`
...
124 | }
| - here, drop of `frame` needs exclusive access to `frame.view`, because the type `SwapChainTexture` implements the `Drop` trait
error[E0505]: cannot move out of `encoder` because it is borrowed
--> src/render_area.rs:122:43
|
96 | impl<'a, 'b> RenderArea where 'a : 'b {
| -- lifetime `'b` defined here
...
107 | let mut render_pass = encoder.begin_render_pass(&wgpu::RenderPassDescriptor {
| -------
| |
| _______________________________borrow of `encoder` occurs here
| |
108 | | color_attachments: &[wgpu::RenderPassColorAttachmentDescriptor {
109 | | attachment: &frame.view,
110 | | resolve_target: None,
... |
116 | | depth_stencil_attachment: None,
117 | | });
| |__________- assignment requires that `encoder` is borrowed for `'b`
...
122 | self.queue.submit(std::iter::once(encoder.finish()));
| ^^^^^^^ move out of `encoder` occurs here
对我来说,这个错误似乎暗示我的生命周期注释表明我想在节点的生命周期中借用传递到我的渲染函数中的 render_pass,但这根本不是我想要做的。我不知道如何正确注释它,有什么想法吗?
感谢@trentcl 指出解决方案。我没有意识到函数可以有独立于特征的生命周期注解,所以我想出了非常复杂的注解,没有正确表达我的意图。简化为以下解决了我的问题
pub trait Node {
fn render<'a>(&'a self, render_pass: &mut wgpu::RenderPass<'a>);
}
...
impl node::Node for RectangleNode {
fn render<'a>(&'a self, render_pass: &mut wgpu::RenderPass<'a>) {
...
render_pass.set_bind_group(0, &self.uniform_bind_group, &[]);
...
}
}
我有以下class
pub struct RectangleNode {
...
uniform_bind_group: wgpu::BindGroup,
...
}
应该实现以下特征
pub trait Node<'a, 'b> where 'a : 'b {
fn render(&'a self, render_pass: &'b mut wgpu::RenderPass);
}
我正在尝试按如下方式进行
impl<'a, 'b> node::Node<'a, 'b> for RectangleNode where 'a : 'b {
fn render(&'a self, render_pass: &'b mut wgpu::RenderPass) {
...
render_pass.set_bind_group(0, &self.uniform_bind_group, &[]);
...
}
}
这(显然?)给了我以下生命周期错误
error[E0495]: cannot infer an appropriate lifetime for borrow expression due to conflicting requirements
--> src/rectangle_node.rs:153:39
|
153 | render_pass.set_bind_group(0, &self.uniform_bind_group, &[]);
| ^^^^^^^^^^^^^^^^^^^^^^^^
|
note: first, the lifetime cannot outlive the lifetime `'a` as defined on the impl at 148:6...
--> src/rectangle_node.rs:148:6
|
148 | impl<'a, 'b> node::Node<'a, 'b> for RectangleNode where 'a : 'b {
| ^^
note: ...so that reference does not outlive borrowed content
--> src/rectangle_node.rs:153:39
|
153 | render_pass.set_bind_group(0, &self.uniform_bind_group, &[]);
| ^^^^^^^^^^^^^^^^^^^^^^^^
note: but, the lifetime must be valid for the anonymous lifetime #1 defined on the method body at 149:5...
--> src/rectangle_node.rs:149:5
|
149 | fn render(&'a self, render_pass: &'b mut wgpu::RenderPass) {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
note: ...so that the types are compatible
--> src/rectangle_node.rs:153:21
|
153 | render_pass.set_bind_group(0, &self.uniform_bind_group, &[]);
| ^^^^^^^^^^^^^^
= note: expected `&mut RenderPass<'_>`
found `&mut RenderPass<'_>`
但我很难理解问题所在。我试图声明 RectangleNode 的生命周期应该比 RenderPass 更长,因为我认为问题是 Rust 需要确保情况如此,但它似乎忽略了我在 RenderPass 上的生命周期注释并假设了一个匿名生命周期为了它?
编辑:
我可以通过更改为
来解决原来的问题impl<'a, 'b> node::Node<'a, 'b> for RectangleNode where 'a : 'b {
fn render(&'a self, render_pass: &mut wgpu::RenderPass<'b>) {
...
render_pass.set_bind_group(0, &self.uniform_bind_group, &[]);
...
}
}
但这现在导致了另一个问题,我尝试使用以下代码
impl<'a, 'b> RenderArea where 'a : 'b {
pub fn render(&mut self, node: &'a dyn Node<'a, 'b>) -> Result<(), wgpu::SwapChainError> {
let frame = self.swap_chain.get_current_frame()?.output;
let mut encoder = self
.device
.create_command_encoder(&wgpu::CommandEncoderDescriptor {
label: Some("Render Encoder"),
});
let mut render_pass = encoder.begin_render_pass(&wgpu::RenderPassDescriptor {
color_attachments: &[wgpu::RenderPassColorAttachmentDescriptor {
attachment: &frame.view,
resolve_target: None,
ops: wgpu::Operations {
load: wgpu::LoadOp::Clear(self.bg_color),
store: true,
},
}],
depth_stencil_attachment: None,
});
node.render(&mut render_pass);
drop(render_pass);
self.queue.submit(std::iter::once(encoder.finish()));
Ok(())
}
}
然后给出以下错误
error[E0597]: `encoder` does not live long enough
--> src/render_area.rs:107:31
|
96 | impl<'a, 'b> RenderArea where 'a : 'b {
| -- lifetime `'b` defined here
...
107 | let mut render_pass = encoder.begin_render_pass(&wgpu::RenderPassDescriptor {
| -^^^^^^
| |
| _______________________________borrowed value does not live long enough
| |
108 | | color_attachments: &[wgpu::RenderPassColorAttachmentDescriptor {
109 | | attachment: &frame.view,
110 | | resolve_target: None,
... |
116 | | depth_stencil_attachment: None,
117 | | });
| |__________- assignment requires that `encoder` is borrowed for `'b`
...
124 | }
| - `encoder` dropped here while still borrowed
error[E0713]: borrow may still be in use when destructor runs
--> src/render_area.rs:109:29
|
96 | impl<'a, 'b> RenderArea where 'a : 'b {
| -- lifetime `'b` defined here
...
107 | let mut render_pass = encoder.begin_render_pass(&wgpu::RenderPassDescriptor {
| _______________________________-
108 | | color_attachments: &[wgpu::RenderPassColorAttachmentDescriptor {
109 | | attachment: &frame.view,
| | ^^^^^^^^^^^
110 | | resolve_target: None,
... |
116 | | depth_stencil_attachment: None,
117 | | });
| |__________- assignment requires that `frame.view` is borrowed for `'b`
...
124 | }
| - here, drop of `frame` needs exclusive access to `frame.view`, because the type `SwapChainTexture` implements the `Drop` trait
error[E0505]: cannot move out of `encoder` because it is borrowed
--> src/render_area.rs:122:43
|
96 | impl<'a, 'b> RenderArea where 'a : 'b {
| -- lifetime `'b` defined here
...
107 | let mut render_pass = encoder.begin_render_pass(&wgpu::RenderPassDescriptor {
| -------
| |
| _______________________________borrow of `encoder` occurs here
| |
108 | | color_attachments: &[wgpu::RenderPassColorAttachmentDescriptor {
109 | | attachment: &frame.view,
110 | | resolve_target: None,
... |
116 | | depth_stencil_attachment: None,
117 | | });
| |__________- assignment requires that `encoder` is borrowed for `'b`
...
122 | self.queue.submit(std::iter::once(encoder.finish()));
| ^^^^^^^ move out of `encoder` occurs here
对我来说,这个错误似乎暗示我的生命周期注释表明我想在节点的生命周期中借用传递到我的渲染函数中的 render_pass,但这根本不是我想要做的。我不知道如何正确注释它,有什么想法吗?
感谢@trentcl 指出解决方案。我没有意识到函数可以有独立于特征的生命周期注解,所以我想出了非常复杂的注解,没有正确表达我的意图。简化为以下解决了我的问题
pub trait Node {
fn render<'a>(&'a self, render_pass: &mut wgpu::RenderPass<'a>);
}
...
impl node::Node for RectangleNode {
fn render<'a>(&'a self, render_pass: &mut wgpu::RenderPass<'a>) {
...
render_pass.set_bind_group(0, &self.uniform_bind_group, &[]);
...
}
}