Here is an example below:
struct Ball { size: u8, } impl Ball { fn update(&mut self, field: &Field) {} } struct Field { ball: Ball, } impl Field { fn update(&mut self) { self.ball.update(self) } }
The root problem is that when you pass a reference to Field you make sure that Field cannot change (the immutable part of the "immutable link"). However, you are also trying to change part of it: the ball! Which link should be reliable, self or Field , in the implementation of Ball::update ?
One solution is to separate parts of the structure necessary for update , and those that are not used and are not used before the update function is called:
struct Ball { size: u8, } impl Ball { fn update(&mut self, field: &u8) {} } struct Field { players: u8, ball: Ball, } impl Field { fn update(&mut self) { self.ball.update(&self.players) } }
You can even combine these fragmented links into a neat package:
struct Ball { size: u8, } impl Ball { fn update(&mut self, field: BallUpdateInfo) {} } struct BallUpdateInfo<'a> { players: &'a u8, } struct Field { players: u8, ball: Ball, } impl Field { fn update(&mut self) { let info = BallUpdateInfo { players: &self.players }; self.ball.update(info) } }
Or restructure your containing structure to share information from the start:
struct Ball { size: u8, } impl Ball { fn update(&mut self, field: &UpdateInfo) {} } struct UpdateInfo { players: u8, } struct Field { update_info: UpdateInfo, ball: Ball, } impl Field { fn update(&mut self) { self.ball.update(&self.update_info) } }
You can also go the other way and remove Ball from Field before making any changes to it. If you can make Ball easily / cheaply, try replacing it:
use std::mem; struct Ball { size: u8, } impl Ball { fn update(&mut self, field: &Field) {} } impl Default for Ball { fn default() -> Ball { Ball { size: 0 } } } struct Field { ball: Ball, } impl Field { fn update(&mut self) { let mut ball = mem::replace(&mut self.ball, Ball::default()); ball.update(self); self.ball = ball; } }
If you cannot easily do this, you can use Option and take it:
struct Ball { size: u8, } impl Ball { fn update(&mut self, field: &Field) {} } struct Field { ball: Option<Ball>, } impl Field { fn update(&mut self) { if let Some(mut ball) = self.ball.take() { ball.update(self); self.ball = Some(ball); } } }