关联类型的生命周期问题
Lifetime Issue with Associated Types
由于生命周期这个令人难以置信的恼人问题,上周我一直在抓狂。
当我尝试在 DataSource
中放置对 Buffer
的引用时出现问题,然后引用 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
必须对第 60 行语句 3 之后的 块后缀有效。我对该错误的解释是 vertex_data_source
应该在第 60 行之前定义。但是要首先创建 vertex_data_source
,我需要访问第 60 行的那些 VertexAttributes
,所以我不能只是调换顺序。
我觉得散落在我的代码上的所有 '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
}
}
}
非常感谢。
编辑:
我更新了代码以更好地反映我的实际实施。
顺便说一句 - 替换这个:
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)
};
没有解决问题。
这允许您的示例编译:
pub struct DrawCommand<'a : 'b, 'b, R: Resources<'a>> {
pub data_source: &'b R::DataSource
}
但是,我发现创建一个更简单的示例非常困难。据我所知,您遇到问题是因为您声明您将持有对本身具有引用的项目的引用,并且这两个引用需要具有共同的生命周期 ('a
)。通过其他生世的某种组合,这实际上是不可能的。
添加第二个生命周期允许引用 到 DataSource
不同于 DataSource
本身的引用。
我仍然会尝试创建一个更小的示例。
由于生命周期这个令人难以置信的恼人问题,上周我一直在抓狂。
当我尝试在 DataSource
中放置对 Buffer
的引用时出现问题,然后引用 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
必须对第 60 行语句 3 之后的 块后缀有效。我对该错误的解释是 vertex_data_source
应该在第 60 行之前定义。但是要首先创建 vertex_data_source
,我需要访问第 60 行的那些 VertexAttributes
,所以我不能只是调换顺序。
我觉得散落在我的代码上的所有 '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
}
}
}
非常感谢。
编辑:
我更新了代码以更好地反映我的实际实施。
顺便说一句 - 替换这个:
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)
};
没有解决问题。
这允许您的示例编译:
pub struct DrawCommand<'a : 'b, 'b, R: Resources<'a>> {
pub data_source: &'b R::DataSource
}
但是,我发现创建一个更简单的示例非常困难。据我所知,您遇到问题是因为您声明您将持有对本身具有引用的项目的引用,并且这两个引用需要具有共同的生命周期 ('a
)。通过其他生世的某种组合,这实际上是不可能的。
添加第二个生命周期允许引用 到 DataSource
不同于 DataSource
本身的引用。
我仍然会尝试创建一个更小的示例。