I'm writing a simple game in Rust, which includes a Drawer, which is constructed once and then passed through many methods as a mutable reference:
pub struct Drawer<'a> {
// ...
renderer: Renderer<'a>,
// ...
}
fn pause(drawer: &mut Drawer, events: &[Event]) {
// ...
drawer.draw_text(&TextPos::Centered, "Paused", 1);
// ...
}
I wanted to refactor my code to introduce a fluent interface for drawing text, such as:
drawer.text()
.size(4)
.centered()
.draw("Paused");
I did this by creating a TextDrawer struct, that contains a reference to the Drawer:
pub struct TextDrawer<'a, 'b: 'a> {
pos: TextPos,
size: u32,
drawer: &'a mut Drawer<'b>,
}
impl<'a> Drawer<'a> {
pub fn text(&mut self) -> TextDrawer {
TextDrawer {
pos: TextPos::At(0, 0),
size: 1,
drawer: self,
}
}
}
I think the lifetimes I've put on the struct are correct (the reference must last as long as the Drawer itself).
However, my text method will not compile until I add explicit lifetimes. When I do, every method that calls text then demands explicit lifetimes, and so on. I'm surprised these lifetimes have to be stated: after all, they're all of the form fn foo<'a, 'b: 'a>(drawer: &mut'a Drawer<'b>). I had assumed before this point that this was already the inferred lifetime, since it was always necessary for the reference to last as long as the Drawer itself.
Is it necessary for me to put these explicit lifetimes all other my method signatures? Or can I avoid it in some other way?
Drawerto something that doesn't have a more common second meaning. At least, assuming it's meant to be pronounced /drɔ ər/ instead of /dror/ - trentcldrawer: &'a mut Drawer<'b>looks wrong, as you don't need to mut on inner types (mutability is inherited by the reference to the type, and everything is mutable in the Type when a reference to it is). - bluejekyll&mut &T(mutable reference to an immutable reference). So the mutable reference inside does make sense (except if I'm missing something crucial here). - Lukas Kalbertodttext()method and it worked. I didn't need to add lifetime parameters to thepause()function for example, that still worked. Could you, Felix, explain your last big paragraph in more detail? Possibly with code and error messages? If my linked solution already helped, please let me know -- I'll make it an answer then. - Lukas Kalbertodt