关联类型的终身问题

neo*_*n64 5 lifetime rust

由于生命中这个令人难以置信的恼人问题,我上周一直在拔头发.

当我尝试将引用放入a Buffer内部时DataSource,会出现问题,然后引用a 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 }
Run Code Online (Sandbox Code Playgroud)

它表示vertex_data_source必须对第60行语句3后面块后缀有效.我对该错误的解释是vertex_data_source应该在第60行之前定义.但是要创建vertex_data_source第一个我需要访问VertexAttributes第60行的那些,所以我不能只是交换订单.

我觉得所有"我的代码上生命周期需要被分成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
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

首先十分感谢.

编辑:

我更新了代码以更好地反映我的实际实现.

顺便说一句 - 替换这个:

let vertex_data_source = factory.create_data_source(vec!(vertices));
Run Code Online (Sandbox Code Playgroud)

有了这个:

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

没有解决问题.

She*_*ter 0

这允许您的示例编译:

pub struct DrawCommand<'a : 'b, 'b, R: Resources<'a>> {
    pub data_source: &'b R::DataSource
}
Run Code Online (Sandbox Code Playgroud)

然而,我发现创建一个更小的示例非常困难。据我所知,您遇到了一个问题,因为您声明您将持有对本身具有引用的项目的引用,并且这两个引用需要具有共同的生命周期('a)。通过其他前世的某种组合,这实际上是不可能的。

添加第二个生命周期允许对 的引用DataSource不同于对自身的引用DataSource

我仍然会尝试创建一个更精简的示例。