title: Managing SDL2 (rust) Texture lifetime
body: <p>I'm going in circles trying to figure out how to properly manage the setup of textures.
  I'm using <a href="https://github.com/Rust-SDL2/rust-sdl2/" rel="nofollow noreferrer">https://github.com/Rust-SDL2/rust-sdl2/</a>. I've tired to extract out a minimal
  example from my whole codebase, so hopefully I haven't missed any details in the
  translation. This is a simple game FYI.</p>
  
  <p>What I'm trying to do is store a <code>TextureCreator</code>[1] and <code>Texture</code>[2] in the same
  struct. What's happening here is SDL makes <code>TextureCreator</code> the owner of every <code>Texture</code>
  created with it, which means I have to use explicit lifetimes. I've got it setup so that I
  can create a new <code>Engine</code> instance with the <code>'a</code> lifetime for the <code>ResMan</code> struct. But as
  soon as I define and call the <code>res_man.load_texture</code> method, things go bonkers and I
  haven't been able to figure out how to properly do it in a way the borrowchecker doesn't
  make me run around in circles. You will notice I used a <code>RefCell</code> to try and attempt to
  fix it, but the borrowchecker seems to want some explicit lifetimes specified in the
  load_texture function.</p>
  
  <p><a href="https://proxy.duckduckgo.com/iu/?u=http%3A%2F%2Fwww.veritasprep.com%2Fblog%2Fwp-content%2Fuploads%2F2015%2F09%2Fi-have-no-idea-what-im-doing-science-dog1-e1441990266456.jpg&amp;f=1" rel="nofollow noreferrer">I'm open to scrapping all of
  this</a>
  for something more rustic if you can enlighten me.</p>
  
  <pre><code>use std::cell::RefCell;
  use std::collections::HashMap;
  
  use sdl2::image::{LoadTexture};
  use sdl2::render::{Canvas, Texture, TextureCreator};
  use sdl2::video::{Window, WindowContext};
  use sdl2::{Sdl, VideoSubsystem};
  
  const BLOCK_TEXTURE_PATH: &amp;str = "../assets/block.png";
  
  fn main() {
      let engine = Engine::new();
      engine.start();
  }
  
  pub struct ResMan&lt;'a&gt; {
      texture_creator: RefCell&lt;TextureCreator&lt;WindowContext&gt;&gt;,
      res_map: HashMap&lt;&amp;'static str, Texture&lt;'a&gt;&gt;,
  }
  
  impl&lt;'a&gt; ResMan&lt;'a&gt; {
      pub fn new(canvas: &amp;Canvas&lt;Window&gt;) -&gt; ResMan&lt;'a&gt; {
  
          ResMan {
              texture_creator: RefCell::new(canvas.texture_creator()),
              res_map: HashMap::with_capacity(10),
          }
      }
  
      // here's horrible code that's on fire,   
      pub fn load_texture(&amp;self, path: &amp;'static str) {
          let texture_creator = self.texture_creator.borrow_mut();
          let block_texture = texture_creator.load_texture(path).unwrap();
          self.res_map.insert(path, block_texture);
      }
  }
  
  pub struct Engine&lt;'a&gt; {
      sdl_context: Sdl,
      video_subsystem: VideoSubsystem,
      canvas: Canvas&lt;Window&gt;,
      res_man: ResMan&lt;'a&gt;,
  }
  
  impl&lt;'a&gt; Engine&lt;'a&gt; {
      pub fn new() -&gt; Engine&lt;'a&gt; {
          let sdl_context = sdl2::init().unwrap();
          let video_subsystem = sdl_context.video().unwrap();
          let window = Engine::open_window(&amp;video_subsystem).unwrap();
          let canvas = Engine::create_canvas(window).unwrap();
          let mut res_man = ResMan::new(&amp;canvas);
          res_man.load_texture(BLOCK_TEXTURE_PATH);
  
          Engine {
              sdl_context,
              video_subsystem,
              canvas,
              res_man,
          }
      }
  
      fn open_window(video_subsystem: &amp;VideoSubsystem) -&gt; Result&lt;Window, String&gt; {
          video_subsystem
              .window("rust-sdl2 demo", 10 * 32, 20 * 32)
              .position_centered()
              .build()
              .map_err(|e| e.to_string())
      }
  
      fn create_canvas(window: Window) -&gt; Result&lt;Canvas&lt;Window&gt;, String&gt; {
          window
              .into_canvas()
              .accelerated()
              .build()
              .map_err(|e| e.to_string())
      }
  
      pub fn start(&amp;self) {
          // main loop
      }
  }
  </code></pre>
  
  <p>1: <a href="https://docs.rs/sdl2/0.32.2/sdl2/render/struct.TextureCreator.html" rel="nofollow noreferrer">https://docs.rs/sdl2/0.32.2/sdl2/render/struct.TextureCreator.html</a></p>
  
  <p>2: <a href="https://docs.rs/sdl2/0.32.2/sdl2/render/struct.Texture.html" rel="nofollow noreferrer">https://docs.rs/sdl2/0.32.2/sdl2/render/struct.Texture.html</a></p>
  
  <hr>
  
  <p>Error message,</p>
  
  <pre><code>error[E0495]: cannot infer an appropriate lifetime for autoref due to conflicting requirements
    --&gt; src/main.rs:31:52
     |
  31 |         let texture_creator = self.texture_creator.borrow_mut();
     |                                                    ^^^^^^^^^^
     |
  note: first, the lifetime cannot outlive the anonymous lifetime #1 defined on the method body at 30:5...
    --&gt; src/main.rs:30:5
     |
  30 | /     pub fn load_texture(&amp;self, path: &amp;'static str) {
  31 | |         let texture_creator = self.texture_creator.borrow_mut();
  32 | |         let block_texture = texture_creator.load_texture(path).unwrap();
  33 | |         self.res_map.insert(path, block_texture);
  34 | |     }
     | |_____^
  note: ...so that reference does not outlive borrowed content
    --&gt; src/main.rs:31:31
     |
  31 |         let texture_creator = self.texture_creator.borrow_mut();
     |                               ^^^^^^^^^^^^^^^^^^^^
  note: but, the lifetime must be valid for the lifetime 'a as defined on the impl at 21:6...
    --&gt; src/main.rs:21:6
     |
  21 | impl&lt;'a&gt; ResMan&lt;'a&gt; {
     |      ^^
     = note: ...so that the expression is assignable:
             expected sdl2::render::Texture&lt;'a&gt;
                found sdl2::render::Texture&lt;'_&gt;
  
  error: aborting due to previous error
  
  error: Could not compile `ffs`.
  </code></pre>