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?