rustlifetimeraw-pointer

How do I figure out where a named lifetime comes from?


I'm reading the code of rust-sdl2 and there's this Texture struct:

pub struct Texture<'r> {
    raw: *mut sys::SDL_Texture,
    _marker: PhantomData<&'r ()>,
}

How do I know where the 'r lifetime comes from?


Solution

  • If the struct was declared like this, then Rust would be able to automatically ensure memory safety:

    pub struct Texture<'r> {
        raw: &'r mut sys::SDL_Texture,
    }
    

    Since the SDL_Texture is managed outside of Rust code this isn't possible because a raw pointer is needed. The lifetime on the Texture is there to add a memory-safe abstraction around an unsafe data structure.

    The crate manages the creation of Textures, and ensures that the lifetimes are always "correct". The lifetime is there to ensure that the texture does not outlive the inner SDL_Texture, which is only referenced by raw pointer.

    You cannot create a Texture yourself, except by unsafe functions. If you were to call TextureCreator::raw_create_texture you'd have to meet all requirements on that lifetime yourself. Instead, the safe method create_texture constructs a Texture, while guaranteeing memory safety.

    The type signature of create_texture is:

    pub fn create_texture<F>(
        &self,
        format: F,
        access: TextureAccess,
        width: u32,
        height: u32,
    ) -> Result<Texture, TextureValueError>
    where
        F: Into<Option<PixelFormatEnum>>,
    

    Some lifetimes are elided. According to Rust's lifetime elision rules, this can be written more explicitly as:

    pub fn create_texture<'r, F>(
        &'r self,
        format: F,
        access: TextureAccess,
        width: u32,
        height: u32,
    ) -> Result<Texture<'r>, TextureValueError>
    where
        F: Into<Option<PixelFormatEnum>>,
    

    The lifetime annotations express a referential dependency between self and the Texture. The returned Texture is therefore not allowed to outlive the TextureCreator.