The simple way to do this is a callback system. Why is that not appropriate for Rust? Does it require custom ownership dynamics that the borrow checker does not support?
The simple way to do this is a callback system. Why is that not appropriate for Rust? Does it require custom ownership dynamics that the borrow checker does not support?
It’s like the classic Joe Armstrong quite about getting the whole jungle when all you wanted is the banana.
You can do it, and if you check out the Gtk/QT bindings you’ll see the boilerplate it introduces. Not insurmountable but many people are interested in figuring out if there’s a better way.
There is a workaround called "internal mutability", an ability to mutate state pointed by a shared pointer. That is syntactically slightly messier, and generally frowned upon. The blog post mentions about this workaround, and also states that it's not ideal so we should strive for better.
I don’t see why this would be frowned upon. It seems to be a runtime version of the borrow checker. For sufficiently dynamic code I don’t see how you can get around checking mutability access at runtime (or asserting that multiple blocks of code aren’t concurrently requesting a mutable reference).
As a comparison, there are many cases where the compiler can prove that a bounds check is unnecessary for accessing an element in a vector but there are also many useful cases where it’s simply not possible to do at compile time. It would be silly to frown upon runtime bounds checks when the requested index or the size of the vector is not known at compile time, a common occurrence in many interesting programs.
I get the motivation to make APIs as statically checkable as possible but it doesn’t seem to always be practical. Reusable UI components can be used in a variety of contexts, e.g. situations with multiple callbacks for different backends. The information is just not always there at compile time.
I don’t think there is a way around this. You’re dealing with a high-level runtime condition. There are no tractable ways to get compilers to understand these higher level runtime conditions, so conditions must be reproven at runtime. It needs an oracle. That oracle should be you but you’ve decided that you cannot be trusted. This appears to be somewhat of a contradiction. Should you even be writing this program in the first place?
This is the "interior mutability" approach that the article mentions.
I think a lot of the problem is really with the confusingness of the concept of static lifetime in rust to begin with, where it's kinda used for both "lives forever" and "doesn't reference anything that lives longer than it"[1]. I hope someday these meanings get different names, tbh.
But when you see that error the naive thought is like... "ok better make it live forever" but it really just means you need to make it something that you control, and there are other ways to do that than a refcounting mutex.
[1] https://doc.rust-lang.org/rust-by-example/scope/lifetime/sta...