Lifetime error for struct with reference

I am trying to have a reference to an image in a struct for a game in ggez but I get errors with the lifetime every time. Here's a part of my code:


pub struct Player<'a> {
    // more player attributes
    pub image: &'a Image,
}
impl<'a> Player<'a> {
   // other player functions
    pub fn set_image(&mut self, image: &'a Image) {
        self.image = image;
    }
}
struct State<'a> {
    // ... more state attributes
    player: Player<'a>,
    images: Vec<Image>,
}
impl<'a> State<'a> {
    fn reset_image(&mut self, ctx: &mut Context) {
        self.player.set_image(&self.images[0]);
    }
    fn new(images: Vec<Image>) -> State<'a> {
        let mut state = State {
            images,
            player: Player {
                // player attributes
                image: &images[0],
            },
        }
    }
}
fn main {
    // setup for ggez
    let images = vec![Image::new(&mut ctx, "/image1.png").unwrap(),
                 Image::new(&mut ctx, "/image2.png").unwrap()];
    let mut state = State::new(images);
    state.reset_everything(&mut ctx);
    event::run(ctx, event_loop, state);
}

And the error message says the following:

error[E0495]: cannot infer an appropriate lifetime for lifetime parameter in function call due to conflicting requirements
   |
86 |         self.player.set_image(&self.images[0]);
   |                                ^^^^^^^^^^^^^^
   |
note: first, the lifetime cannot outlive the anonymous lifetime defined here...
   |
82 |     fn reset_everything(&mut self, ctx: &mut Context) {
   |                         ^^^^^^^^^
note: ...so that reference does not outlive borrowed content
   |
86 |         self.player.set_image(&self.images[0]);
   |                                ^^^^^^^^^^^
note: but, the lifetime must be valid for the lifetime `'a` as defined here...
   |
59 | impl<'a> State<'a> {
   |      ^^
note: ...so that the types are compatible
   |
86 |         self.player.set_image(&self.images[0]);
   |                     ^^^^^^^^^
   = note: expected `&mut Player<'_>`
              found `&mut Player<'a>`

I am new to Rust so if someone could help me, that would be great!

Why does the player hold an image reference and not the image itself? Also, the proper way to do this in a game engine is to make a new type that function's as a handle to the image, and you give that to the player; then you store the images in a hashmap that maps handles to actual images.

BUT, the issue with your code is not only that, the issue is a lifetime conflict:

 // Here, the Self inside the impl item is a State<'a>, that holds a Player<'a>
impl<'a> State<'a> {
  // However, here, the &mut self parameter creates an anonymous lifetime for self (it's the same as &'_ mut self)
  fn reset_image(&mut self, ctx: &mut Context) {
    self.player.set_image(&self.images[0]);
  }

To fix this, all you need to do is use an explicit lifetime on the method, like so:

impl<'a> State<'a> {
  fn reset_image(&'a mut self, ctx: &mut Context) {
    self.player.set_image(&self.images[0]);
  }

Here's the docs on lifetimes: Validating References with Lifetimes - The Rust Programming Language

But again, consider using a HashMap for your images and handles to access them

2 Likes

Thank you I think that solved it. But what do you mean by handle to acces the images? How would that work out?

How would that work out?

You'd keep all images in a collection type such as Vec or HashMap, and hand out the keys to the images in that collection. Caveat is you'd need to access the collection every time you'd want to get the actual image

1 Like