Last active
May 12, 2018 15:31
-
-
Save ennis/eadedc8120b731aa869dc4a5ab53f36d to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
extern crate nanovg as nvg; | |
use std::rc::Rc; | |
use std::cell::RefCell; | |
use std::collections::HashMap; | |
struct ImageCache<'ctx> | |
{ | |
context: &'ctx nvg::Context, | |
// Remove RefCell and it compiles | |
cache: RefCell<HashMap<String,Rc<nvg::Image<'ctx>>>>, | |
} | |
impl<'ctx> ImageCache<'ctx> | |
{ | |
fn new(context: &'ctx nvg::Context) -> ImageCache<'ctx> { | |
unimplemented!() | |
} | |
} | |
struct Renderer<'cache,'ctx:'cache> | |
{ | |
frame: nvg::Frame<'ctx>, | |
cache: &'cache ImageCache<'ctx>, | |
} | |
impl<'cache,'ctx:'cache> Renderer<'cache,'ctx> { | |
pub fn new(frame: nvg::Frame<'ctx>, cache: &'cache ImageCache<'ctx>) -> Renderer<'cache,'ctx> { | |
Renderer { | |
frame, | |
cache | |
} | |
} | |
} | |
fn main() | |
{ | |
// dummy context | |
let context: nvg::Context = unimplemented!(); | |
let cache = ImageCache::new(&context); | |
// cache: Cache<'A>, with 'A being a concrete lifetime inferred by the compiler | |
{ | |
context.frame(unimplemented!(), unimplemented!(), |frame| { | |
// Here is what **I think** happens: | |
// | |
// here we borrow cache: ImageCache<'A>, and pass it to `Renderer::new'. | |
// Thus, within `new()', the compiler infers: | |
// | |
// 'ctx='A because the 'ctx parameter of ImageCache is pinned by the RefCell (see below) | |
// | |
// and | |
// | |
// (1) frame: Frame<'A> | |
// | |
// However, the bounds on the f (the closure passed to frame()) are | |
// | |
// F: FnOnce(Frame) | |
// | |
// which desugars (with lifetime elision) to: | |
// | |
// (2) F: for <'a> FnOnce(Frame<'a>) | |
// | |
// which roughly means that the closure must be valid for all lifetimes 'a, | |
// i.e. that `frame()' can only take closures that accepts **any** kind of Frame | |
// (i.e. no constraint on the 'ctx parameter of Frame<'ctx>) | |
// | |
// But borrowing `cache' in the closure leads to (1), and adds a constraint on the | |
// 'ctx lifetime parameter on the frame passed as a parameter to the closure ('ctx='A), | |
// which is incompatible with (2). Thus the error. | |
// | |
// Coincidentally, removing the RefCell in ImageCache makes ImageCache variant over 'ctx. | |
// so that the compiler is free to choose another lifetime when borrowing `cache'. | |
// Thus the borrow will have type ImageCache<'B> where 'A: 'B. This relaxes the bounds on 'ctx. | |
// Disclaimer: I'm not sure to fully understand this. | |
// error: borrowed data cannot be stored outside of its closure | |
let mut renderer = Renderer::new(frame, &cache); | |
}); | |
} | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment