In Rust, how do you explicitly tie the lifetimes of two objects together, without referencing eachother?

lifetime, opengl, reference, rust

Solution

This is one of the primary use cases for the `PhantomData` type, as demonstrated there in an example.

Applied to this case, you’ll end up with something like this:

use std::marker::PhantomData;

struct VertexArray<'a> {
    id: GLuint,
    vbo_lifetime: PhantomData<&'a VertexBuffer>,
}

And instantiation will be something like this:

    fn make<'a>(&'a self) -> VertexArray<'a> {
        VertexArray {
            id: …,
            vbo_lifetime: PhantomData,
        }
    }

(This is eliding the generic type, allowing it to be inferred; you could also write `PhantomData::<&'a VertexBuffer>`.)

Problem

The specific case where I ran into this was in using OpenGL, writing `struct`s for a `VertexBuffer` and `VertexArray`. Each struct is, in essence, a single `GLuint` that refers to the OpenGL object. In the simplest case, a `VertexArray` has exactly one `VertexBuffer` associated with it. The problem is that the `VertexArray` cannot live longer than its associated `VertexBuffer`. Rust doesn't know this though, since the reference that the `VertexArray` holds is internal to OpenGL, so it will have no problem calling the destructor on the `VertexBuffer` while an existing `VertexArray` references it. The current solution I have is to put a reference in manually, which goes unused: ``` struct VertexArray<'a> { id: GLuint, #[warn(dead_code)] vbo: &'a VertexBuffer } ``` In more complex cases, the reference might turn out to be necessary, but it feels inelegant and wasteful. A VAO with multiple VBOs could be implemented with an array/vector of references. Being able to change the associated buffers after the VAO has been created might also add this requirement. Is there any way to achieve this same behaviour without the reference? Or, since the compiler can recognize that the reference is never used and give a warning, will it be optimized out?

Original source