Changing contents of an array via its reference

69 Views Asked by At

I've been recently working with the following scenario:

pub fn random_function(inp_array: &[u32]) {

    for actual_val in (RefCell::new(*inp_array)).iter_mut() {
        // change actual_val to e.g., constant number so that it's reflected in inp_array
    }

Given a function that takes as input a reference to an immutable u32 array, I'm trying to change its contents via a smart pointer. I'm still kind of new to interior mutability concept; the snipped above has the following issue:

error[E0277]: the size for values of type `[u32]` cannot be known at compilation time
error[E0599]: no method named `iter_mut` found for struct `RefCell` in the current scope

I'm not entirely sure what is the correct pattern here. Any ideas? thanks!

2

There are 2 best solutions below

1
cafce25 On BEST ANSWER

You can't change anything behind a shared reference unless it is already in a UnsafeCell (for example via RefCell). The most likely version you want is to take a mutable reference instead:

pub fn random_function(inp: &mut [u32]) {
    for actual_val in inp {
        // change actual_val to e.g., constant number so that it's reflected in inp_array
        *actual_val += 10;
    }
}

If you want to use interior mutability, the parts that you want to mutate have to be wrapped in a struct supporting that already. So you could take &[RefCell<u32>]

use std::cell::RefCell;
pub fn random_function(inp: &[RefCell<u32>]) {
    for actual_val in inp {
        // change actual_val to e.g., constant number so that it's reflected in inp_array
        *actual_val.borrow_mut() += 10;
    }
}

or &RefCell<impl AsMut<[u32]>>

use std::cell::RefCell;
pub fn random_function(inp: &RefCell<impl AsMut<[u32]>>) {
    for actual_val in inp.borrow_mut().as_mut() {
        // change actual_val to e.g., constant number so that it's reflected in inp_array
        *actual_val += 10;
    }
}
0
Finomnis On
  • "takes as input a reference to an immutable u32"
  • "trying to change its contents"

Those two statements are incompatible. You cannot mutate a reference to an immutable variable without unsafe. And even then, it would be unsound.

If your function needs to modify values in the inp_array, it must take it as an &mut [u32].

You can of course use interior mutability for this purpose, but then the type must be a &RefCell or &Mutex or their respective ref-counted counterparts, Rc<RefCell> or Arc<Mutex>.