How to make a struct with a persistant borrow of one of it's own fields

i'm trying to wrap sdl2 in an abstraction layer, but the borrow checker is giving me trouble.

use sdl2::Sdl;
use sdl2::pixels::Color;
use sdl2::event::Event;
use sdl2::keyboard::Keycode;
use sdl2::ttf::{Sdl2TtfContext, Font};

// apperently NixOS doesn't have fonts in any of the places you would expect.
static FONT: &[u8] = include_bytes!("SomeFont.ttf");


pub struct SdlWindow<'a> {
	sdl: Sdl,
	ttf: Sdl2TtfContext,
	font: Option<Font<'a, 'a>>,
}

impl SdlWindow<'_> {
	fn new() -> Box<Self> {
		let fontrw = sdl2::rwops::RWops::from_bytes(FONT).unwrap();
		let sdl = sdl2::init().unwrap();
		let ttf = sdl2::ttf::init().unwrap();
		let mut w = Box::new(SdlWindow{
			sdl,
			ttf,
			font: None,
		});
		w.font = Some(w.ttf.load_font_from_rwops(fontrw, 16).unwrap());
		
		w
	}
}

my only idea currently is to make the Sdl2TtfContext have a static lifetime, but that means its destructor will never be run, possibly leaking persistent resources like tempfiles or X server PixBufs, so i would like to avoid that. maybe something could be done involving Pin, but i'm not sure.

There's no useful way to do it with safe code.

There's a few crates that try to encapsulate self-referencial structs, like ouroboros. It's very hard to do soundly (there may still be some unsound corner cases).

Alternatives include keeping the owner and the borrower separate and working below the call stack where you join the two, and recreating the borrower only when you need it.

Incidentally here's a recent thread about the same SDL2 Font challenge, linking to an issue about it. I haven't taken the time to see if there's an idiomatic solution, but perhaps the breadcrumbs will help.

1 Like

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.