Error: explicit lifetime required in the type

I have clear instruction from Rust pre-compile analyzer telling me:

&mut Sprite<Texture<Resources>>

Go to [Sprite](#) | [Texture](#) | [Resources](#)

explicit lifetime required in the type of `sprite_hash`
lifetime `'a` requiredrustc(E0621)

main.rs(38, 32): add explicit lifetime `'a` to the type of `sprite_hash`

[Peek Problem (Alt+F8)](#)

No quick fixes available

I know I need to apply a lifetime to the type of 'sprite_hash' but I don't see how to do it. Please advise.
Here's the code: (the return var 'sprite' is what's underlined in red in VSCode)

fn get_sprite<'a>(sprite_hash: &mut HashMap<Point, SpriteID>, piece_type: ChessPiece, piece_position: &Point) -> &'a mut Sprite<Texture<gfx_device_gl::Resources>> {
    let sprite: &mut Sprite<Texture<gfx_device_gl::Resources>>;
    match sprite_hash.get_mut(piece_position) {
        Some(structure) => {
            if structure.sprite_piecetype == ChessPiece::BlackBishop {
                println!("BlackBishop");
            }
            sprite = &mut structure.sprite_image_instance;
            sprite.set_position(piece_position.top_left_x as f64, piece_position.top_left_y as f64);
            println!("Made it");
        },
        _ => println!("No piece found."),
    }
    sprite
}

Try to change the type of sprite_hash in your function signature to &'a mut HashMap<Point, SpriteID>?

- fn get_sprite<'a>(sprite_hash: &mut HashMap<Point, SpriteID>, piece_type: ChessPiece, piece_position: &Point) -> &'a mut Sprite<Texture<gfx_device_gl::Resources>> {
+ fn get_sprite<'a>(sprite_hash: &'a mut HashMap<Point, SpriteID>, piece_type: ChessPiece, piece_position: &Point) -> &'a mut Sprite<Texture<gfx_device_gl::Resources>> {

Please post error messages from cargo build instead of your IDE, as they are much more complete with information.

@alice Your suggestion is good; don't know why I didn't think of running the compiler for more info. It turns out the borrow checker is telling me I can't have a function return a reference var to a HashMap entry since the entry or even the HashMap could cease to exist, making the ref var a dangling pointer; lifetime of ref var can't be greater than lifetime of HashMap.

Your interpretation of the problem is correct, but this doesn't mean that you cannot write a function like the one you posted; we just need to convince the borrow checker that the reference you return (&'a mut Sprite<Texture<gfx_device_gl::Resources>>) will not outlive the HashMap that it comes from.

In order to do this, as the error message you posted suggests, we need to indicate to the borrow checker that the HashMap is borrowed for as long as the reference that's returned is:

- fn get_sprite<'a>(sprite_hash: &mut HashMap<Point, SpriteID>, piece_type: ChessPiece, piece_position: &Point) -> &'a mut Sprite<Texture<gfx_device_gl::Resources>> {
+ fn get_sprite<'a>(sprite_hash: &'a mut HashMap<Point, SpriteID>, piece_type: ChessPiece, piece_position: &Point) -> &'a mut Sprite<Texture<gfx_device_gl::Resources>> {

Because the HashMap is borrowed for as long as the Sprite reference you return is, there's no danger that the reference you return will become a dangling pointer (put differently, the reference cannot outlive the HashMap) Note that this also guards against the other problem case you mention (the specific HashMap entry that you return a reference to ceasing to exist): because mutable borrows are exclusive, no one else can mutably borrow the HashMap instance which means no mutable operations (such as removing or modifying entries) can be performed on the HashMap while your reference is still alive.

Here's a small example showing that, if you add the lifetime to the HashMap's reference, this kind of thing compiles:

use std::collections::HashMap;

#[derive(PartialEq, Eq, Hash)]
struct Key;
struct Value;

fn get_element<'a>(map: &'a mut HashMap<Key, Value>, key: &Key) -> Option<&'a mut Value> {
    map.get_mut(key)
}

(Playground)

Though, for the function you posted, I think you'll also run into an error about how sprite is potentially uninitialized when the function returns (as in, what do you want to return when the Point isn't in the HashMap?).

@rrbutani You are so correct about all including the error about how sprite is potentially uninitialized when the function returns; so how is the best way to get rid of this error?

As mentioned, you need to decide what you want to do when the sprite you're looking for isn't in the HashMap.

If this isn't expected/isn't something that you can recover from, you can panic! in the other arm of the match (i.e. change println!("No piece found.") to panic!("No piece found.")).

If this is something that the caller can/should deal with, you can change the function to return an Option. As in, something like this:

fn get_sprite<'a>(sprite_hash: &'a mut HashMap<Point, SpriteID>, piece_type: ChessPiece, piece_position: &Point) -> Option<&'a mut Sprite<Texture<gfx_device_gl::Resources>> {
    let sprite: Option<&mut Sprite<Texture<gfx_device_gl::Resources>>>;
    match sprite_hash.get_mut(piece_position) {
        Some(structure) => {
            if structure.sprite_piecetype == ChessPiece::BlackBishop {
                println!("BlackBishop");
            }
            structure.sprite_image_instance.set_position(piece_position.top_left_x as f64, piece_position.top_left_y as f64);
            sprite = Some(&mut structure.sprite_image_instance);
            println!("Made it");
        },
        _ => {
            println!("No piece found.");
            sprite = None;
        }
    }
    sprite
}

Alternatively:

fn get_sprite<'a>(
    sprite_hash: &'a mut HashMap<Point, SpriteID>,
    piece_type: ChessPiece,
    piece_position: &Point,
) -> Option<&'a mut Sprite<Texture<gfx_device_gl::Resources>> {
    sprite_hash.get_mut(piece_position)
        .map(|p| {
            if p.sprite_piecetype == ChessPiece::BlackBishop {
                println!("BlackBishop");
            }
            
            p.sprite_image_instance.set_position(
                piece_position.top_left_x as f64,
                piece_position.top_left_y as f64,
            );
            
            &mut p.sprite_image_instance
        })
}

@rrbutani Wow! Thank you so much. This was an incredibly educational experience. Thanks again!

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.