The crate cosmic_text recommends a single instance of FontSystem and SwashCache<'a> per application.
This is the example they give:
let font_system = FontSystem::new();
let mut cache = SwashCache::new(&font_system);
// Do text rendering
And you can proceed with your text-rendering desires as needed. But since their recommendation to keep these two instances across the application, I'm left with a connundrum. Rust doesn't seem to allow me to do this, because cache holds a reference to font_system. Immutable or not, this now means it cannot move (i.e. placing it into a struct or whatnot)
So I tried pinning it.
let font_system = Box::pin(FontSystem::new());
let mut cache = SwashCache::new(font_system.deref());
// Do text rendering
Which works if I use it like that, but I still can't place it into a struct. Now theoretically, I know why Rust won't allow me to do this, but I don't seem to know how to progress.
My goal is to implement a rich-text editor using cosmic_text, where I'd like to be able to reuse the SwashCache<'a> and FontSystem, for performance and memory consumption reasons.
So to summarise this wall of text, how can I reuse these two values, ideally avoiding unsafe code, keeping the SwashCache<'a> in an Option / lateinit values?
Rust doesn't provide any safe way to do that. Here's an unsafe way to do it: playground
Note that it's not sound to provide methods that return mutable references to them. In the case of FontSystem, this is because the cache holds a reference to it. In the case of SwashCache, this is because the caller could mem::swap it.
That said, it would be ok to provide methods like these:
Safe (or rather safely abstracted, so you don’t need to touch the unsafety yourself) solutions are probably possible via crates such as ouroboros - Rust.
From doing soundness reviews on ouroboros (and some other comparable crates), I know there’s an insane amount of subtle ways to get such “self-referencing” data structures wrong. While some of the more subtle points perhaps/maybe only apply to soundness of generalist crates that try to offer support for all possible types, where every component could have different variance, possibly custom drop implementations, there could be chains of borrowing, etc, etc…, the fact that I cannot keep the list of “all surprising issues that came up over multiple occasions of on and off reviewing (on different self-referencing-structs crates)” in my head in the first place means that I personally would generally avoid to hand-write my own self-referencing data structure, unless I have a good reason to do so.
To name another crate I’ve done some review on and that might work for you as well, self_cell - Rust is a more minimalistic crate here which does not need any procedural macros parsing facilities and does not support anything fancy beyond simply two fields, one immutably borrowing the other.
It does seem somewhat like black magic to be able to just install a crate and suddenly it just works, so thank you for assuring me my gut feeling is right
Using self-referential types is usually a bad idea, even if you use popular crates to provide the unsafe bits. I would suggest creating the required structures somewhere at the top level (possibly even as a static variable), and passing them down to consuming functions. This way you never need to move them.
The reason the first fails is because the lazy_static macro doesn't ensure the variable is declared at compile-time, but rather the code necessary to initialise it is, thus the compiler doesn't know the reference to FONT is valid at all.
The reason the second failed is clear to me, it's the same reason all the others fail - because the value of font_system moves, so the reference to it is invalidated.
The third failed because neiterh FontSystem::new() nor SwashCache::new(&FontSystem) are const, allowing them to be initialised in a static or a const