Cannot borrow data in a `&` reference as mutable

When I try the following

use std::sync::Arc;

fn main() {
    let v: Arc<Vec<u8>> = Arc::from(Vec::new());
    v.push(1);
    v.push(2);
    println!("{:#?}", v);
}

I get this error:

error[E0596]: cannot borrow data in a `&` reference as mutable
 --> test.rs:5:5
  |
5 |     v.push(1);
  |     ^ cannot borrow as mutable

error[E0596]: cannot borrow data in a `&` reference as mutable
 --> test.rs:6:5
  |
6 |     v.push(2);
  |     ^ cannot borrow as mutable

error: aborting due to 2 previous errors

Why doesn't this work?

Arc only doles out & references to the inside because otherwise you could get aliasing pointers:

use std::sync::Arc;

fn main() {
    let v: Arc<Vec<u8>> = Arc::from(vec![1]);
    let v2 = v.clone();

    let first = &v[0];
    v2.extend(0..20); // this could cause the vec to reallocate
    println!("{:#?}", first); // use after free
}

To enable mutation of the things inside, you need a type that offers interior mutability through runtime aliasing checks, such as Mutex, RwLock, or RefCell.

use std::sync::{Arc, Mutex};

fn main() {
    let v = Arc::new(Mutex::new(vec![1]));
    let v2 = v.clone();

    let guard = v.try_lock().unwrap();
    let first = &guard[0];
    v2.try_lock().unwrap().extend(0..20); // this now panics
    println!("{:#?}", first); // unreachable
}
1 Like

And there's Arc::make_mut which will make a copy if needed.

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.