Lifetime issue with related types

I have been pulling my hair out in the last week because of this incredibly annoying problem with a lifetime.

The problem occurs when I try to put a reference to Buffer inside a DataSource , which then refers to DrawCommand . I get an error: vertex_data_source does not live long enough .

 src/main.rs:65:23: 65:41 error: src/main.rs:65 data_source: &vertex_data_source ^~~~~~~~~~~~~~~~~~ src/main.rs:60:51: 67:2 note: reference must be valid for the block suffix following statement 3 at 60:50... src/main.rs:60 let vertices = VertexAttributes::new(&buffer); src/main.rs:61 src/main.rs:62 let vertex_data_source = factory.create_data_source(vertices); src/main.rs:63 src/main.rs:64 let command: DrawCommand<ResourcesImpl> = DrawCommand { src/main.rs:65 data_source: &vertex_data_source ... src/main.rs:62:67: 67:2 note: ...but borrowed value is only valid for the block suffix following statement 4 at 62:66 src/main.rs:62 let vertex_data_source = factory.create_data_source(vertices); src/main.rs:63 src/main.rs:64 let command: DrawCommand<ResourcesImpl> = DrawCommand { src/main.rs:65 data_source: &vertex_data_source src/main.rs:66 }; src/main.rs:67 } 

He says that vertex_data_source must be valid for the suffix of the block following statement 3 on line 60. My interpretation of this error is that vertex_data_source must be defined before line 60 . But to create a vertex_data_source , first of all I need access to those VertexAttributes on line 60, so I can’t just change the order around.

It seems to me that all the lives sprinkled with my code need to be divided by 2 or maybe just deleted, however I tried every combination that seemed reasonable, and I'm not from the idea.

Below is a very simplified example of my code that demonstrates the problem. I would really appreciate a sanity check and hopefully a fresh mind could identify the problem. (every time before a few days of feedling released a fix, but this time I'm at a standstill).

 use std::cell::RefCell; use std::marker::PhantomData; pub struct DrawCommand<'a, R: Resources<'a>> { pub data_source: &'a R::DataSource } pub trait Resources<'a> { type DataSource: 'a; type Buffer: 'a; } pub struct DataSource<'a> { id: u32, attributes: Vec<VertexAttributes<'a, ResourcesImpl<'a>>>, current_element_array_buffer_binding: RefCell<Option<Buffer<'a>>> } pub struct Buffer<'a> { context: &'a GraphicsContextImpl } pub struct GraphicsContextImpl; pub struct ResourcesImpl<'a> { phantom: PhantomData<&'a u32> // 'a is the lifetime of the context reference } impl<'a> Resources<'a> for ResourcesImpl<'a> { type Buffer = Buffer<'a>; type DataSource = DataSource<'a>; } struct Factory<'a> { context: &'a GraphicsContextImpl } impl<'a> Factory<'a> { /// Creates a buffer fn create_buffer<T>(&self) -> Buffer<'a> { Buffer { context: self.context } } fn create_data_source(&self, attributes: Vec<VertexAttributes<'a, ResourcesImpl<'a>>>) -> DataSource<'a> { DataSource { id: 0, attributes: attributes, current_element_array_buffer_binding: RefCell::new(None) } } } fn main() { let context = GraphicsContextImpl; let factory = Factory { context: &context }; let buffer = factory.create_buffer::<u32>(); let vertices = VertexAttributes::new(&buffer); let vertex_data_source = factory.create_data_source(vec!(vertices)); let command: DrawCommand<ResourcesImpl> = DrawCommand { data_source: &vertex_data_source }; } pub struct VertexAttributes<'a, R: Resources<'a>> { pub buffer: &'a R::Buffer, } impl<'a, R: Resources<'a>> VertexAttributes<'a, R> { pub fn new(buffer: &'a R::Buffer) -> VertexAttributes<'a, R> { VertexAttributes { buffer: buffer } } } 

Thank you very well in advance.

EDIT:

I updated the code to better reflect my actual implementation.

By the way, replacing this:

 let vertex_data_source = factory.create_data_source(vec!(vertices)); 

Wherein:

 let vertex_data_source = DataSource { id: 0, attributes: vec!(vertices), current_element_array_buffer_binding: RefCell::new(None) }; 

Does not solve the problem.

+5
source share
1 answer

This allows you to compile your example:

 pub struct DrawCommand<'a : 'b, 'b, R: Resources<'a>> { pub data_source: &'b R::DataSource } 

However, it is very difficult for me to create a more minimal example. As far as I can tell, you have a problem because you declare that you will refer to an element that itself has a link, and that these two links should have a common lifetime ( 'a ). Thanks to some combination of other lives, this is virtually impossible.

Adding a second lifetime allows the link to the DataSource be different from the link to the DataSource itself.

I'm still trying to create a more miniature example.

0
source

All Articles