Я вытаскиваю свои волосы за последнюю неделю из-за этой невероятно раздражающей проблемы со временем жизни.Пожизненная проблема со связанными типами
Проблема возникает, когда я пытаюсь поместить ссылку на Buffer
внутри DataSource
, которая затем ссылается на DrawCommand
. Я получаю сообщение об ошибке: vertex_data_source
не живет достаточно долго.
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 }
Это говорит vertex_data_source
должен быть действительным для блока суффикса после заявления 3 в строке 60. Моя интерпретация этой ошибки заключается в том, что vertex_data_source
должен быть определен до строки 60. Но для создания vertex_data_source
в первую очередь мне нужен доступ к тем VertexAttributes
на линии 60, поэтому я не могу просто поменять порядок.
Я чувствую, что все 'a жизни, посыпанные моим кодом, нужно разделить на 2 или, возможно, просто удалить, однако я пробовал каждую комбинацию, которая казалась разумной, и я не из идей.
Ниже приведен очень упрощенный пример моего кода, который демонстрирует проблему. Я был бы очень признателен за проверку здравомыслия и, надеюсь, свежий ум мог бы определить проблему. (каждый раз, прежде чем несколько дней фидлинга выпустили исправление, но на этот раз я в тупике).
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
}
}
}
Большое спасибо за внимание.
EDIT:
Я обновил код, чтобы лучше отразить мою фактическую реализацию.
Кстати - замена этого:
let vertex_data_source = factory.create_data_source(vec!(vertices));
С этим:
let vertex_data_source = DataSource {
id: 0,
attributes: vec!(vertices),
current_element_array_buffer_binding: RefCell::new(None)
};
Не решает эту проблему.
Это довольно длинный снимок, но может быть, так как вы перемещаете «вершины» в 'create_data_source' и возвращаетесь с тем же временем жизни, это время жизни уже завершено, когда функция возвращается? – MartinHaTh
Я пытался это исправить, но вы упростили код до такой степени, что я не могу сказать, что происходит. Решение - «вырезать кучу, казалось бы, бессмысленного кода», но это вряд ли будет тем, что вы хотите. Например, почему 'attributes 'передается' create_data_source', когда он никогда не используется? Почему 'create_data_source' метод на' Factory', когда он никогда не ссылается на него? Почему '' a' используется в этом методе, несмотря на включение * ничего * с этой жизнью? Я могу сказать вам, почему вы получаете эту ошибку, но я не могу начать предлагать, как исправить это, не имея более четкого представления о том, что вы делаете ... –
Вот как я до этого отказался: http: //is.gd/khBtaO –