So, I was writing some code and apparently R.A. didn't warn me about some erroneous stuff I had written in regards to how ownership works with lambdas.
So, a friend helped me rewrite some of my code, and this is just a play example, but their new code boils down to this:
let vec = Rc::new(RwLock::new( Vec::new() ));
let vec_rc = vec.clone();
let my_lambda = || -> () {
vec_rc.write().unwrap().push(/* ... */);
}
But what I don't understand is how this works if vec_rc
isn't mut
.
From my prior knowledge, mutable in Rust cascades; in other words, if the "master-containing" object is immutable the rest will have to be too.
Could I please get some clarity as to what goes on under the hood?
Or is their code erroneous too?
From my prior knowledge, mutable in Rust cascades; in other words, if the "master-containing" object is immutable the rest will have to be too.
This is almost always true... Until we consider interior mutability.
Interior mutability is exactly about that: changing a value through a shared reference. Moreover, while there are other shared references to it. The basic interior mutability primitive is UnsafeCell
, but there are multiple abstractions built on top of it - one of them is RwLock
(you can see it secretly contains an UnsafeCell
).
As a side note, Rc<RwLock<T>>
is almost always wrong: Rc
is non thread safe, which defeats the whole purpose of RwLock
. If you just need shared mutable stated over one thread, use Rc<RefCell<T>>
. It is much more performant and can't block (so no deadlock debugging, just a simple panic if something went wrong).