Hi everyone,
I'm trying and failing to understand why the following code doesn't compile.
use std::sync::Arc;
struct Foo {
bar: Vec<i32>
}
impl Foo {
pub fn baz(&mut self, num: i32) {
self.bar.push(num);
}
}
fn main() {
let mut foo = Foo { bar: vec!() };
let arc_foo = Arc::new(foo);
let quux_foo = arc_foo.clone();
let quux = move |num| {
quux_foo.baz(num);
};
quux(1);
let print_foo = arc_foo.clone();
println!("{:?}", print_foo.bar);
}
It produces the following error, but I'm not entirely sure how to read it.
error: cannot borrow immutable borrowed content as mutable
--> <anon>:19:9
|>
19 |> quux_foo.baz(num);
|> ^^^^^^^^
Does this mean that quux_foo
is immutable? I've tried using the mut
keyword (let mut quux_foo
) too. I guess my understanding of move
closures is not quite there.
Here's the same code on Rust Playground: Rust Playground
Any help would be much appreciated!
Yup!
It's not actually the move closure that's the issue, it's that Arc
holds something that's immutable. If you want to mutate the insides of the arc, you'll need to put a Mutex
or RwLock
inside.
2 Likes
This is because Arc
does not implement DerefMut
. In simpler terms, it won't give you an &mut
to modify the contained object through. This is because of Rust's particular opinion on shared references and mutability: they are mutually exclusive.
Because you're using Arc
and a move
closure, I assume you're tinkering with threads. In this case, you'll want to use a Mutex
, which allows two or more threads with shared references to a value (e.g. through an Arc
) to request mutable access to that value one at a time; concurrent attempts to modify will allow one thread to continue executing with a mutable reference while all the other threads are blocked.
The Mutex
API docs helpfully include an example on usage. I also recommend the Rust Programming Language chapter on Concurrency for further reading.
2 Likes
@steveklabnik @DroidLogician Thanks so much for the quick and helpful responses! <3
That's good to know. I need to do more reading on Mutex
/RwLock
.
For anyone who finds this thread in the future, here's an updated example that actually compiles.
1 Like