关联类型的终身问题

时间:2015-07-24 08:59:59

标签: rust lifetime

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

当我尝试在tickValues([0,1])中引用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 } 必须对第60行语句3后面的块后缀有效。我对该错误的解释是 vertex_data_source应该在第60行之前定义。但是要首先创建vertex_data_source我需要在第60行访问那些vertex_data_source,所以我不能只是交换订单。

我觉得我的代码上的所有'a 生命周期都需要分成2个或者可能只是删除了,但是我尝试了所有看起来合理的组合并且我没有离开想法。

以下是我的代码的一个非常简化的示例,用于演示此问题。我非常感谢理智检查,希望新思维能够发现问题。 (每次摆弄几天之前都会产生修复,但这次我很难过。)

VertexAttributes

非常感谢。

修改

我已更新代码以更好地反映我的实际实施情况。

顺便说一句 - 替换这个:

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
        }
    }
}

有了这个:

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

无法解决问题。

1 个答案:

答案 0 :(得分:0)

这允许您的示例编译:

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

但是,我发现创建一个更小的例子非常困难。我可以确定,您有一个问题,因为您声明您将持有对自身具有引用的项的引用,并且这两个引用需要具有共同的生命周期('a)。通过其他生命周期的某种组合,这实际上是不可能的。

添加第二个生命周期允许引用 DataSourceDataSource本身的引用不同。

我仍然会尝试创建一个更小的例子。