Lifetimes error

Hello!
I will be as brief as possible with this example.

I have one World with 2 fields: Levels and Players

pub struct World<'a>{
  levels: Vec<Level<'a>>,
  players: Vec<Player>
}

In the Levels, I have Platforms and the Players that are in the current level

pub struct Level<'a> {
  platforms: Vec<Platform>,
  players: Vec<&'a Player>
}

So, imagine when I start the game I want to pass all players reference from World to level 1 and if one player finish level 1 pass the reference to level2.

My code:

impl<'a> World <'a>{
  pub fn new() -> World <'a>{
    World{
      levels: vec![],
      players: vec![],
    }
  }

  pub fn new_player(&mut self, id: u32, name: String){
    let player = Player::new(id, name);
    self.players.push(player);
  }

  pub fn new_level(&mut self) -> &mut Level<'a>{
    let level = Level::new();
    self.levels.push(level);
    self.levels.get_mut(self.levels.len() - 1).unwrap()
  }

  pub fn start(&mut self){
    let level = self.new_level();
    for player in &self.players{
      level.add_player(player);
    }
  }
}

impl<'a> Level <'a>{
  pub fn new() -> Self{
    Level {
      platforms: vec![],
      players: vec![]
    }
  }

  pub fn add_player(&mut self, player: &'a Player){
    self.players.push(player);
  }
}

My error is in function start at &self.players: cannot infer an appropriate lifetime for borrow expression due to conflicting requirements

Don't use references here. References are not general pointers, they are inherently temporary. You want something more permanent, so you have two options:

  1. use indicies instead, this requires you to explicitly pass around World.players to whatever needs access to it
pub struct World {
  levels: Vec<Level>,
  players: Vec<Player>
}
pub struct Level<'a> {
  platforms: Vec<Platform>,
  players: Vec<usize> // index into World.players
} 
  • Use Rc/Arc to share Player
pub struct World {
  levels: Vec<Level>,
  players: Vec<Rc<Player>>
}
pub struct Level<'a> {
  platforms: Vec<Platform>,
  players: Vec<Rc<Player>>
} 

This will make Player immutable by default and requires shared mutable types like RefCell or Mutex to regain mutability.

In the words of @kornel:
Using lifetimes in structs is an advanced feature, and you shouldn't use it until you understand other parts of Rust.

1 Like

To understand why references don't work, when you write this:

pub struct World<'a>{
  levels: Vec<Level<'a>>,
  players: Vec<Player>
}

This means "the field levels contains references pointing somewhere outside the World struct", so when you try to do something else, such as making it pointing into World itself, it will notice the inconsistency and fail to compile.

2 Likes