Error: type annotation requires that borrow lasts for `'static`


#1

Hello,
Sorry to bother you but I have an error on my rust code. I use the Piston crate and I want to put a Piston Window in a struct so I did that but it does not work.

use std::collections::HashMap;

use opengl_graphics::{TextureSettings,OpenGL};
use piston_window::{Texture,G2dTexture,PistonWindow,Event};
use crate::Traits::Drawable;
use piston_window::WindowSettings;

pub struct GameRenderer {
    txt_map: HashMap<&'static str,&'static G2dTexture>,
    window: &'static PistonWindow,
    scene_map: HashMap<&'static str,&'static G2dTexture>,
}

impl Drawable for GameRenderer {

    fn draw(&mut self,window: &mut GameRenderer,e: &Event) {

    }
}

impl GameRenderer {

    pub fn new(x: u32,y: u32,title: &str) -> GameRenderer {
        let opengl = OpenGL::V3_2;
        let mut window: &'static PistonWindow = &mut(
            WindowSettings::new(title, [x, y])
                .exit_on_esc(true)
                .opengl(opengl)
                .vsync(true)
                .resizable(false)
                .decorated(true)
                .build()
                .unwrap());
        return GameRenderer{window: window,scene_map: HashMap::new(),txt_map: HashMap::new()};
    }
}

And the error

  --> src/GameRenderer.rs:25:53
   |
25 |           let mut window: &'static PistonWindow = &mut(
   |  _________________________---------------------_______^
   | |                         |
   | |                         type annotation requires that borrow lasts for `'static`
26 | |             WindowSettings::new(title, [x, y])
27 | |                 .exit_on_esc(true)
28 | |                 .opengl(opengl)
...  |
32 | |                 .build()
33 | |                 .unwrap());
   | |__________________________^ creates a temporary which is freed while still in use
34 |           return GameRenderer{window: window,scene_map: HashMap::new(),txt_map: HashMap::new()};
35 |       }
   |       - temporary value is freed at the end of this statement

Thanks in advance for the answer.
ccgauche.
Excuse me for the quality of my english but I am french :slight_smile: :fr:


#2

Some advice, don’t annotate lifetimes until the compiler complains about it.

In this case you are borrowing a temporary value, this generally doesn’t work. Instead you can just do

let mut window : PistonWindow = WindowSettings::new(title, [x, y])
                .exit_on_esc(true)
                .opengl(opengl)
                .vsync(true)
                .resizable(false)
                .decorated(true)
                .build()
                .unwrap();

In GameRenderer you can take ownership of PistonWindow.

pub struct GameRenderer {
    txt_map: HashMap<&'static str,&'static G2dTexture>,
    window: PistonWindow,
    scene_map: HashMap<&'static str,&'static G2dTexture>,
}

Following along with the last bit, in general don’t store references inside of structs. This will invariably lead to lifetimes infecting everywhere it is used. This can lead to poor readability.
Because of this, it would be better to try and store the G2dTexture directly inside of the GameRenderer.

An exception to the last rule is if you are storing string literals, (&'static str), this is fine because string literals are all known at compile time and are hard-coded in.

So overall the GameRenderer would probably be better of as

pub struct GameRenderer {
    txt_map: HashMap<&'static str, G2dTexture>,
    window: PistonWindow,
    scene_map: HashMap<&'static str, G2dTexture>,
}

#3

Thank’s to you I’ve learnt something today.