Lifetime question


#1
use std::marker::PhantomData;

struct Engine<'a, C, B>
    where C: Canvas<'a>,
          B: Backend<'a, C>
{
    backend: B,
    a_lifetime_marker: PhantomData<&'a mut ()>,
    c_marker: PhantomData<C>,
}

impl<'a, C, B> Engine<'a, C, B>
    where C: Canvas<'a>,
          B: Backend<'a, C>
{
    fn new(backend: B) -> Self {
        Engine {
            backend: backend,
            a_lifetime_marker: PhantomData::default(),
            c_marker: PhantomData::default(),
        }
    }
    
    fn run<'b, A>(&'b mut self, app: &mut A)
        where A: Application<'b, C, B>
    {
        loop {
            {
                let context = UpdateContext {
                    engine: self,
                };
                app.update(context);
            }
            {
                let canvas = self.backend.canvas();
            }
        }
    }
}

trait Backend<'a, C>
    where C: Canvas<'a>
{
    fn canvas(&'a mut self) -> C;
}

struct SimpleBackend<'a> {
    a_marker: PhantomData<&'a mut ()>,
}

impl<'a> SimpleBackend<'a> {
    fn new() -> Self {
        SimpleBackend {
            a_marker: PhantomData::default(),
        }
    }
}

impl<'a> Backend<'a, SimpleCanvas<'a>> for SimpleBackend<'a> {
    fn canvas(&'a mut self) -> SimpleCanvas<'a> {
        SimpleCanvas {
            backend: self,
        }
    }
}

trait Canvas<'a>: 'a {
}

struct SimpleCanvas<'a> {
    backend: &'a mut SimpleBackend<'a>
}

impl<'a> Canvas<'a> for SimpleCanvas<'a> {
}

trait StartableApplication<'a, C, B>
    where C: Canvas<'a>,
          B: Backend<'a, C>
{
    type Application: Application<'a, C, B>;
    
    fn start(self, engine: &mut Engine<'a, C, B>) -> Self::Application;
}

struct SimpleStartableApplication;

impl<'a, C, B> StartableApplication<'a, C, B> for SimpleStartableApplication
    where C: Canvas<'a>,
          B: Backend<'a, C>
{
    type Application = SimpleApplication;
    
    fn start(self, engine: &mut Engine<'a, C, B>) -> Self::Application {
        SimpleApplication
    }
}

trait Application<'a, C, B>
    where C: Canvas<'a>,
          B: Backend<'a, C>
{
    fn render(&mut self, canvas: &mut C);
    fn update<'b>(&mut self, context: UpdateContext<'b, 'a, C, B>);
}

struct UpdateContext<'a, 'b, C, B>
    where 'b: 'a,
           C: Canvas<'b>,
           B: Backend<'b, C> + 'a
{
    engine: &'a mut Engine<'b, C, B>,
}

struct SimpleApplication;

impl<'a, C, B> Application<'a, C, B> for SimpleApplication
    where C: Canvas<'a>,
          B: Backend<'a, C>
{
    fn render(&mut self, canvas: &mut C) {
        
    }
    
    fn update<'b>(&mut self, context: UpdateContext<'b, 'a, C, B>) {
        
    }
}

fn main() {
    let backend = SimpleBackend::new();
    let mut engine = Engine::new(backend);
    let app = SimpleStartableApplication;
    let mut app: SimpleApplication = app.start(&mut engine);
    engine.run(&mut app);
    println!("Hello, world!");
}

I am stuck please help me.


#2

Why did you start a new topic on this? It looks like it’s very related to your question(s) here Lifetime problem


#3

Previous question was with higher-ranked lifetimes.


#4

If I understand correct, then I need higher ranked types
to make

trait Backend<C>
    where C: Canvas
{
    fn canvas<'a>(&'a mut self) -> C<'a>;
}

#5

This was replied to over here How to declare trait function with associated type in result:


#6

Let me check it.


#7

Could you please explain

trait Backend<'a> {
    type Canvas: 'a;
    
    fn canvas(&'a mut self) -> Self::Canvas;
}

what constaint imples &'a in &'a mut self


#8

as @jethrogb replied (in the other thread) isn’t it better to ask about it there?


#9

Here is changed version:

use std::marker::PhantomData;

struct Engine<'a, B>
    where B: Backend<'a>
{
    backend: B,
    a_lifetime_marker: PhantomData<&'a mut ()>,
}

impl<'a, B> Engine<'a, B>
    where B: Backend<'a>
{
    fn new(backend: B) -> Self {
        Engine {
            backend: backend,
            a_lifetime_marker: PhantomData::default(),
        }
    }
    
    fn run<A>(&mut self, app: &mut A)
        where A: Application<'a, B>
    {
        loop {
            {
                // let context = UpdateContext {
                    // engine: self,
                // };
                // app.update(context);
            }
            {
                let canvas = self.backend.canvas();
            }
        }
    }
}

trait Backend<'a>
{
    type Canvas: Canvas + 'a;
    
    fn canvas(&'a mut self) -> Self::Canvas;
}

struct SimpleBackend<'a> {
    a_marker: PhantomData<&'a mut ()>,
}

impl<'a> SimpleBackend<'a> {
    fn new() -> Self {
        SimpleBackend {
            a_marker: PhantomData::default(),
        }
    }
}

impl<'a> Backend<'a> for SimpleBackend<'a> {
    type Canvas = SimpleCanvas<'a>;
    
    fn canvas(&'a mut self) -> SimpleCanvas<'a> {
        SimpleCanvas {
            backend: self,
        }
    }
}

trait Canvas {
}

struct SimpleCanvas<'a> {
    backend: &'a mut SimpleBackend<'a>
}

impl<'a> Canvas for SimpleCanvas<'a> {
}

trait StartableApplication<'a, B>
    where B: Backend<'a>
{
    type Application: Application<'a, B>;
    
    fn start(self, engine: &mut Engine<'a, B>) -> Self::Application;
}

struct SimpleStartableApplication;

impl<'a, B> StartableApplication<'a, B> for SimpleStartableApplication
    where B: Backend<'a>
{
    type Application = SimpleApplication;
    
    fn start(self, engine: &mut Engine<'a, B>) -> Self::Application {
        SimpleApplication
    }
}

trait Application<'a, B>
    where B: Backend<'a>
{
    fn render(&mut self, canvas: &mut B::Canvas);
    fn update<'b>(&mut self, context: UpdateContext<'b, 'a, B>);
}

struct UpdateContext<'a, 'b, B>
    where 'b: 'a,
           B: Backend<'b> + 'b
{
    engine: &'a mut Engine<'b, B>,
}

struct SimpleApplication;

impl<'a, B> Application<'a, B> for SimpleApplication
    where B: Backend<'a>
{
    fn render(&mut self, canvas: &mut B::Canvas) {
        
    }
    
    fn update<'b>(&mut self, context: UpdateContext<'b, 'a, B>) {
        
    }
}

fn main() {
    let backend = SimpleBackend::new();
    let mut engine = Engine::new(backend);
    let app = SimpleStartableApplication;
    let mut app: SimpleApplication = app.start(&mut engine);
    engine.run(&mut app);
    println!("Hello, world!");
}

Error:

src/main.rs:31:43: 31:49 error: cannot infer an appropriate lifetime for autoref due to conflicting requirements [E0495]
src/main.rs:31                 let canvas = self.backend.canvas();
                                                         ^~~~~~
src/main.rs:20:5: 34:6 help: consider using an explicit lifetime parameter as shown: fn run<A>(&'a mut self, app: &mut A) where A: Application<'a, B>
src/main.rs:20     fn run<A>(&mut self, app: &mut A)

If I add 'a to &mut self then another error:

src/main.rs:31:30: 31:42 error: cannot borrow `self.backend` as mutable more than once at a time [E0499]
src/main.rs:31                 let canvas = self.backend.canvas();
                                            ^~~~~~~~~~~~
src/main.rs:31                 let canvas = self.backend.canvas();
                                            ^~~~~~~~~~~~
src/main.rs:31     }
                   ^

#10

This may be used as workaround:

use std::marker::PhantomData;

struct Engine<B>
    where B: Backend
{
    backend: B,
}

impl<B> Engine<B>
    where B: Backend
{
    fn new(backend: B) -> Self {
        Engine {
            backend: backend,
        }
    }
    
    fn run<A>(&mut self, app: &mut A)
        where A: Application<B>
    {
        loop {
            {
                let context = UpdateContext {
                    engine: self,
                };
                app.update(context);
            }
            app.render(self.backend.canvas());
        }
    }
}

trait Backend
{
    type Canvas: Canvas;
    
    fn canvas(&mut self) -> &mut Self::Canvas;
}

struct SimpleBackend {
    canvas: SimpleCanvas,
}

impl SimpleBackend {
    fn new() -> Self {
        SimpleBackend {
            canvas: SimpleCanvas {
            }
        }
    }
}

impl Backend for SimpleBackend {
    type Canvas = SimpleCanvas;
    
    fn canvas(&mut self) -> &mut Self::Canvas {
        &mut self.canvas
    }
}

trait Canvas {
}

struct SimpleCanvas {
}

impl Canvas for SimpleCanvas {
}

trait StartableApplication<B>
    where B: Backend
{
    type Application: Application<B>;
    
    fn start(self, engine: &mut Engine<B>) -> Self::Application;
}

struct SimpleStartableApplication;

impl<B> StartableApplication<B> for SimpleStartableApplication
    where B: Backend
{
    type Application = SimpleApplication;
    
    fn start(self, engine: &mut Engine<B>) -> Self::Application {
        SimpleApplication
    }
}

trait Application<B>
    where B: Backend
{
    fn render(&mut self, canvas: &mut B::Canvas);
    fn update<'b>(&mut self, context: UpdateContext<'b, B>);
}

struct UpdateContext<'a, B>
    where B: Backend + 'a
{
    engine: &'a mut Engine<B>,
}

struct SimpleApplication;

impl<B> Application<B> for SimpleApplication
    where B: Backend
{
    fn render(&mut self, canvas: &mut B::Canvas) {
        
    }
    
    fn update<'b>(&mut self, context: UpdateContext<'b, B>) {
        
    }
}

fn main() {
    let backend = SimpleBackend::new();
    let mut engine = Engine::new(backend);
    let app = SimpleStartableApplication;
    let mut app: SimpleApplication = app.start(&mut engine);
    engine.run(&mut app);
    println!("Hello, world!");
}