A question for the class about rust lifetimes / "self-referential" structs: I have the following structs:
pub struct Renderer<'a> {
surface: wgpu::Surface<'a>,
config: wgpu::SurfaceConfiguration,
device: Device,
queue: Queue,
}
Renderer is what is sounds like. The lifetime param on the surface (from wgpu) is defined by the lifetime of the window I am creating (surface stores a reference to the window), it is created like this:
impl<'a> Renderer<'a> {
pub fn new(window: &'a Window) -> Renderer<'a> {
let size = window.inner_size();
let instance = Instance::default();
let surface = instance.create_surface(window).unwrap();
...
Renderer {
surface,
device,
queue,
config,
}
}
So far this is all fine, but I want to have a structure that stores both the window and my renderer:
pub struct Application {
window: Window,
renderer: Renderer,
}
Ofc this has the problem that the lifetime parameter 'a is not defined for Renderer, but as far as I can tell there is no way in rust to have renderer use the lifetime of window , the best I can do is this:
pub struct Application<'a> {
window: winit::Window,
renderer: Renderer<'a>,
}
but this has the problem that when I define Application like so:
let window = winit::window::WindowBuilder::new()
.build(&event_loop)
.unwrap();
let mut renderer = Renderer::new(&window);
let mut app = Application {
window,
renderer
};
I get the following error:
|
21 | let window = winit::window::WindowBuilder::new()
| ------ binding `window` declared here
...
25 | let mut renderer = Renderer::new(&window);
| ------- borrow of `window` occurs here
...
28 | window,
| ^^^^^^ move out of `window` occurs here
29 | renderer
| -------- borrow later used here
which makes sense, because the lifetime of renderer is in no way tied to the lifetime of window in the struct definition, as it needs to be. I have found a variety of (what seem to me to be) hacks using Pin and unsafe stuff, which I could do, but part of my goal of learning rust it rethink the way I write programs. I think what I'm trying to do here might be very "C++", and I'm wondering whether there might be a different high-level approach I could use that would be more rust friendly.
I'm wondering if anyone might have any ideas. The reason I want Application to store both window and renderer is application is responsible for handling the update loop and handling window messages, so it needs access to the window (to handle the messages) and the renderer (to tell it to render, as well as to respond to some messages: e.g. a resize). I think maybe I could make renderer a singleton of sorts (not sure if there's a safe way to do this in rust, I think maybe not?) Or I can just pass through my renderer everywhere I guess but I don't love that (but maybe that's just C++ brain talking). Would love to hear anyone's thoughts on how to approach this kind of thing I'd really appreciate it!