Wyciągam włosy z zeszłego tygodnia z powodu tego niesamowicie irytującego problemu z wcieleniami.Dożywotnia wersja z powiązanymi typami
Problem pojawia się, gdy próbuję umieścić odniesienie do Buffer
wewnątrz DataSource
, który następnie odwołuje się do DrawCommand
. Otrzymuję komunikat o błędzie: vertex_data_source
nie żyje wystarczająco długo.
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 }
Mówi vertex_data_source
musi być ważny dla przyrostka bloku następującym stwierdzeniem 3 w wierszu 60. Moja interpretacja tego błędu polega na tym, że przed linią 60 należy zdefiniować vertex_data_source
. Ale w celu stworzenia vertex_data_source
przede wszystkim potrzebuję dostępu do tych VertexAttributes
na linii 60, więc nie mogę po prostu zamieniać kolejność.
Czuję, że wszystkie lata życia nad moim kodem muszą zostać podzielone na 2, a może po prostu usunięte, jednak próbowałem każdej kombinacji, która wydawała się rozsądna i nie mam pomysłów.
Poniżej znajduje się znacznie uproszczony przykład mojego kodu, który demonstruje problem. Byłbym wdzięczny za sprawdzenie zdrowego rozsądku i mam nadzieję, że świeży umysł będzie w stanie wykryć problem. (za każdym razem, zanim kilka dni grania stworzyło poprawkę, ale tym razem jestem zaskoczony).
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
}
}
}
Dziękuję bardzo z góry.
EDIT:
I został uaktualniony kod, aby lepiej odzwierciedlały moją rzeczywistą realizację.
Nawiasem mówiąc - zastępując w ten sposób:
let vertex_data_source = factory.create_data_source(vec!(vertices));
z tym:
let vertex_data_source = DataSource {
id: 0,
attributes: vec!(vertices),
current_element_array_buffer_binding: RefCell::new(None)
};
nie rozwiązuje problemu.
To całkiem długie ujęcie, ale czy możliwe jest, że od przeniesienia 'wierzchołków' do' create_data_source' i powracania z tym samym okresem życia, to życie już się skończyło, gdy funkcja wróci? – MartinHaTh
Próbowałem to rozwiązać, ale uprościłeś kod do tego stopnia, że nie mogę powiedzieć, co się dzieje. Rozwiązaniem jest "wyrwać kupkę pozornie bezsensownego kodu", ale to raczej nie jest to, czego chcesz. Na przykład, dlaczego 'attributes' przekazano do' create_data_source', kiedy nigdy nie jest używane? Dlaczego 'create_data_source' jest metodą na' Factory', kiedy nigdy się do niej nie odnosi? Dlaczego "a" jest używane w tej metodzie, mimo że w tym życiu nie ma * nic? Mogę ci powiedzieć, dlaczego dostajesz ten błąd, ale nie mogę zacząć sugerować, jak to naprawić bez lepszego zrozumienia tego, co robisz ... –
Oto moja dotychczasowa decyzja: http: //is.gd/khBtaO –