I'm trying to use some code from another crate for my custom implementation and stumbled upon the following code:
fn style_to_font<S: BackendTextStyle>(style: &S) -> Font {
// iced font family requires static str
static mut FONTS: Lazy<HashSet<String>> = Lazy::new(HashSet::new);
Font {
family: match style.family() {
FontFamily::Serif => font::Family::Serif,
FontFamily::SansSerif => font::Family::SansSerif,
FontFamily::Monospace => font::Family::Monospace,
FontFamily::Name(s) => {
let s = unsafe {
if !FONTS.contains(s) {
FONTS.insert(String::from(s));
}
FONTS.get(s).unwrap().as_str()
};
font::Family::Name(s)
}
},
weight: match style.style() {
FontStyle::Bold => font::Weight::Bold,
_ => font::Weight::Normal,
},
..Font::DEFAULT
}
}
Which gives me the following lint:
1 warning: creating a shared reference to mutable static is discouraged
--> src/backend.rs:331:25
|
331 | if !FONTS.contains(s) {
| ^^^^^^^^^^^^^^^^^ shared reference to mutable static
|
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/static-mut-references.html>
= note: shared references to mutable statics are dangerous; it's undefined behavior if the static is mutated or if a mutable reference is created for it while the shared reference lives
= note: `#[warn(static_mut_refs)]` on by default
I have looked at the given link, but can not come up with a solution for this. Maybe someone can explain the details and probably give a hint for a better implementation.
Thank you both, I first tried the solution from @alice, but couldn't make the borrow checker happy, then I combined it with the code from @quinedot and now it works.
Just for my understanding, static gives FONTS a precise location in memory, thus I can share the references to it's contained str? What would happen, if I remove elements from the BTreeSet?
No, because the Mutex doesn't allow you to keep references to its contents after you release the lock.
This is an example which would result in a use-aftee-free kind of bug if Mutex did allow you to keep references to its contents. However it does not allow that, so when you remove elements from the BTreeSet you can be sure there is nothing referencing them.