I have a boring version of Pacman in C that I'm adapting into Rust to learn about Rust. I have this large structure that contains information about the actors and their graphics.
I have a situation where I want to use a short-hand for two different pieces of the data-structure, spr
and actor
. But I get errors because self
is borrowed multiple times. The code is here and doesn't work:
// update Pacman sprite
{
let spr = self.spr_pacman();
if spr.enabled {
let actor = &self.game.pacman.actor;
spr.pos = actor.pos.actor_to_sprite_pos();
if (self.game.freeze & FreezeType::EatGhost as u8) != 0 {
// hide Pacman shortly after he's eaten a ghost (via an invisible Sprite tile)
spr.tile = SPRITETILE_INVISIBLE;
} else if (self.game.freeze & (FreezeType::Prelude as u8 | FreezeType::Ready as u8)) != 0 {
// special case game frozen at start of round, show Pacman with 'closed mouth'
spr.tile = SPRITETILE_PACMAN_CLOSED_MOUTH;
} else if (self.game.freeze & FreezeType::Dead as u8) != 0 {
// play the Pacman-death-animation after a short pause
if self
.timing
.after(self.game.pacman_eaten, PACMAN_EATEN_TICKS as u32)
{
self.spr_anim_pacman_death(
self.timing.since(self.game.pacman_eaten) - PACMAN_EATEN_TICKS as u32,
);
}
} else {
// regular Pacman animation
self.spr_anim_pacman(actor.dir, actor.anim_tick);
}
}
}
If I just copy and past the definition of spr
and actor
into every one of their uses the code DOES work:
// update Pacman sprite
{
if self.spr_pacman().enabled {
self.spr_pacman().pos = self.game.pacman.actor.pos.actor_to_sprite_pos();
if (self.game.freeze & FreezeType::EatGhost as u8) != 0 {
// hide Pacman shortly after he's eaten a ghost (via an invisible Sprite tile)
self.spr_pacman().tile = SPRITETILE_INVISIBLE;
} else if (self.game.freeze & (FreezeType::Prelude as u8 | FreezeType::Ready as u8)) != 0 {
// special case game frozen at start of round, show Pacman with 'closed mouth'
self.spr_pacman().tile = SPRITETILE_PACMAN_CLOSED_MOUTH;
} else if (self.game.freeze & FreezeType::Dead as u8) != 0 {
// play the Pacman-death-animation after a short pause
if self
.timing
.after(self.game.pacman_eaten, PACMAN_EATEN_TICKS as u32)
{
self.spr_anim_pacman_death(
self.timing.since(self.game.pacman_eaten) - PACMAN_EATEN_TICKS as u32,
);
}
} else {
// regular Pacman animation
self.spr_anim_pacman(self.game.pacman.actor.dir, self.game.pacman.actor.anim_tick);
}
}
}
I understand why the original version is dangerous, because I could send the two references to different places and it would be very bad. In this circumstance, though, it is safe.
Is there a "call-by-name" version of let
that does a "copy & paste" like this? I feel like this would be a common macro but I don't know enough about the Rust world to know what to search for to find it.