As alice said, the usual way to modify something inside of a container is by having mutable access to the container itself. To give some code example
#[derive(Debug)]
struct SomeObject {
field1: i32,
field2: f32,
}
fn main() {
// let’s heap allocate the objects individually for no reason
let o1 = Box::new(SomeObject {
field1: 42,
field2: 3.1415926,
});
let o2 = Box::new(SomeObject {
field1: 12345,
field2: -2.5,
});
// put it into a container, e.g. a Vec
let mut x: Vec<Box<SomeObject>> = vec![o1, o2];
// and let’s mutate it in the_rest_of_my_program
the_rest_of_my_program(&mut x);
// let’s see the results
println!("{:#?}", x);
}
fn the_rest_of_my_program(container: &mut Vec<Box<SomeObject>>) {
// can mutate the container itself
container.push(Box::new(SomeObject {
field1: 0,
field2: 0.0,
}));
// as well as the objects inside
container[1].field2 = 1_000_000.0;
}
(in the playground)
Output:
[
SomeObject {
field1: 42,
field2: 3.1415925,
},
SomeObject {
field1: 12345,
field2: 1000000.0,
},
SomeObject {
field1: 0,
field2: 0.0,
},
]
I’m also not 100% sure what you understand under the term “heap object”. Usually heap vs. stack doesn’t make a difference when it comes to whether something can be modified in Rust or not. Of course, there are ownership primitives such as Rc
that are implemented using the heap and that also do influence whether or how things can be modified.
If you want to learn more about Rc
and RefCell
in general, you could read the Smart Pointers chapter of the book. (Understanding those may also require some knowledge from most of the previous chapters, too.)
If you are having trouble or are uncertain about certain aspects of Rc
or RefCell
, feel free to ask more concrete questions. Or if you’re trying to figure out which of these you might need to implement a specific algorithm or solve a specific problem.