Reputation: 2921
I'm attempting to mutate a struct that is a member of a vector within another struct. Despite reading the documentation and many, many articles on ownership, I'm still obviously missing something because I cannot get the following, relatively trivial code to work.
I'm getting a compiler error on the line add_content(&mut bar);
which says cannot borrow data in a '&' reference as mutable
, which I know is true, but I cannot figure how to get it to work.
I've been reading about Box<T>
, Cell<T>
and RefCell<T>
and wondering if I might need to make use of one of those but I'm very unfamiliar with them and it seems like my trivial example below should work without extra complications.
#[derive(Debug)]
struct Foo {
id: u32,
bars: Vec<Bar>,
}
#[derive(Debug)]
struct Bar {
id: u32,
content: String,
}
fn main() {
let mut foos: Vec<Foo> = Vec::new();
foos.push(Foo {
id: 100,
bars: Vec::new(),
});
foos[0].bars.push(Bar {
id: 200,
content: String::new(),
});
loops(&foos);
println!("{:#?}", foos);
}
fn loops(foos: &Vec<Foo>) {
for foo in foos {
for mut bar in &foo.bars {
add_content(&mut bar);
}
}
}
fn add_content(bar: &mut Bar) {
bar.content = String::from("hello");
}
Note that my example is deliberately trivial. My actual program is more involved but I've tried to boil down the problem to just the part that's giving me a headache.
How can I get the above code to work?
Upvotes: 2
Views: 335
Reputation: 39457
You need to pass in mutable reference to vector because you are modifying elements of the vector.
#[derive(Debug)]
struct Foo {
id: u32,
bars: Vec<Bar>,
}
#[derive(Debug)]
struct Bar {
id: u32,
content: String,
}
fn main() {
let mut foos: Vec<Foo> = Vec::new();
foos.push(Foo {
id: 100,
bars: Vec::new(),
});
foos[0].bars.push(Bar {
id: 200,
content: String::new(),
});
loops(&mut foos);
println!("{:#?}", foos);
}
fn loops(foos: &mut Vec<Foo>) {
for foo in foos {
for bar in &mut foo.bars {
add_content(bar);
}
}
}
fn add_content(bar: &mut Bar) {
bar.content = String::from("hello");
}
Upvotes: 2
Reputation: 23245
You need to add mut
at every level of your data hierarchy:
fn loops(foos: &mut Vec<Foo>) {
for foo in foos {
for mut bar in &mut foo.bars {
add_content(&mut bar);
}
}
}
Upvotes: 0
Reputation: 1526
Obviously, you can not borrow a &mut
from a &
. And it seems that you messed up the types of foo
bar
. Change your code into something like this:
fn main() {
let mut foos: Vec<Foo> = Vec::new();
foos.push(Foo {
id: 100,
bars: Vec::new(),
});
foos[0].bars.push(Bar {
id: 200,
content: String::new(),
});
loops(&mut foos); // look at here
println!("{:#?}", foos);
}
fn loops(foos: &mut Vec<Foo>) { // here
for foo in foos {
for bar in &mut foo.bars { // here
add_content(bar); // and here
}
}
}
or
fn main() {
// the same
}
fn loops(foos: &mut Vec<Foo>) {
for foo in foos.iter_mut() {
for bar in foo.bars.iter_mut() {
add_content(bar);
}
}
}
Upvotes: 2