1

我有以下课程

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,但这根本不想做。我不知道如何正确注释这个,有什么想法吗?

4

1 回答 1

2

感谢@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, &[]);
        ...
    }
}
于 2021-03-07T06:18:59.493 回答