Changing key of HashMap from child method
<p>I'm working on a 2D sandbox game that implements tiles in piston. The basic structure of this is an <code>App</code> struct, which stores a <code>world: World</code> struct, which has a <code>tiles: HashMap</code> property of <code>Box&lt;Tile&gt;</code>s, with the key being an X-Y position of where the tile is.</p>

<p>To render this, I loop through the coordinates of every tile space on the screen and if there is a tile in the hashmap with those co-ordinates, I call <code>tile.render(&amp;context, &amp;mut gl);</code>.</p>

<p>I now need to implement a <code>Tile.update()</code> method which will be called each update, however this method would need to have the ability to modify the co-ordinates of the block which means modifying the key of the tile itself in the hashmap, but I can't pass the hashmap to the <code>tile.update()</code> function since accessing the tile would borrow the hashmap.</p>

<p>How do I accomplish this in the least hacky/most elegant way possible? Is there a better method I should be using to store the tiles that will allow this to work? Changing the co-ordinates from outside the <code>Tile.update()</code> method is not possible.</p>

<p>This is pretty much what I'm trying to do. I know why it won't work, I'm just not sure how to get around it:</p>

<pre><code>use std::collections::HashMap;
use std::boxed::Box;

pub trait Tile {
    fn new(x: i32, y: i32) -&gt; Self where Self: Sized;
    fn render(&amp;self, camera_x: i32, camera_y: i32);
    fn update(&amp;mut self, app: &amp;mut App);
}

pub struct DirtTile {
    pub x: i32,
    pub y: i32,
}

impl Tile for DirtTile {
    fn new(x: i32, y: i32) -&gt; DirtTile {
        return DirtTile { x: x, y: y };
    }

    fn render(&amp;self, camera_x: i32, camera_y: i32) {
        // render
    }

    fn update(&amp;mut self, app: &amp;mut App) {
        let world = app.world;

        // update pos
        let new_pos = [self.x + 1, self.y];
        if world.tiles.get(&amp;new_pos).is_none() {
            world.tiles.remove(&amp;[self.x, self.y]);
            world.tiles.insert(new_pos, Box::new(*self));
            self.x = new_pos[0];
            self.y = new_pos[1];
        }
    }
}

pub struct World {
    tiles: HashMap&lt;[i32; 2], Box&lt;Tile&gt;&gt;,
}

pub struct App {
    world: World,
}

fn main() {
    let mut app = App { world: World { tiles: HashMap::new() } };

    app.world.tiles.insert([0, 0], Box::new(DirtTile::new(0, 0)));

    for (xy, tile) in &amp;app.world.tiles {
        tile.update(&amp;mut app);
    }
}
</code></pre>

<p><a href="https://play.rust-lang.org/?gist=30ac409603b9b42117565fe756e7b5e2&amp;version=stable&amp;backtrace=0" rel="nofollow">Playground</a></p>