Reputation: 91
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?
Upvotes: 0
Views: 123
Reputation: 91
Thanks to the minimal example made by Lukas above, I realised I had simply got the lifetime parameters to my text
method backwards.
My incorrect lifetimes:
impl<'a> Drawer<'a> {
pub fn text<'b>(&'b mut self) -> TextDrawer<'a, 'b> {
// omitted
}
}
The correct lifetimes:
impl<'a> Drawer<'a> {
pub fn text<'b>(&'b mut self) -> TextDrawer<'b, 'a> {
// omitted
}
}
After this, everything compiles without any further explicit lifetimes.
Upvotes: 1