Reputation: 680
First of all I want to apologise for this noob question with an unspecific title, I'm quite new to Rust.
Anyway, here is some (working) code:
struct A {
data: i32
}
struct B<'s> {
a: &'s A
}
impl<'s> B<'s> {
fn new(reference: &'s A) -> B<'s> {
B {
a: reference
}
}
}
fn main() {
let a1 = A{data: 0};
let b1 = B::new(&a1);
let b2 = B::new(&a1);
}
There is a struct A with some data and a struct B that contains an immutable reference to A. In the main method several B-objects are created with references to a single A-object.
Now I only want to change one thing: In the B::new() method I want to modify the data of 'reference' before using it as the immutable member of B. I tried it like this:
struct A {
data: i32
}
struct B<'s> {
a: &'s A
}
impl<'s> B<'s> {
fn new(reference: &'s mut A) -> B<'s> {
// Modify data
reference.data += 1;
B {
a: reference
}
}
}
fn main() {
let mut a1 = A{data: 0};
let b1 = B::new(&mut a1);
let b2 = B::new(&mut a1);
}
But the compiler won't let me, error: cannot borrow a1
as mutable more than once at a time. Why isn't the mutable borrow over once new() has finished? What would be the proper way to achieve what I'm trying?
Upvotes: 3
Views: 1695
Reputation: 1562
As @AndreaP said, the issue is because of your reference with the same lifetime.
Usually you can work around these issues by simply splitting your functions (one &
and one &mut
).
If you really need this kind on pattern, then I think what you are looking for is Cell
/RefCell
: http://doc.rust-lang.org/std/cell/index.html
EDIT: Thanks to @Ker comment, I updated the code so B
indeed holds a reference to A
instead of its copy. Old code was just totally wrong.
use std::cell::{Cell};
#[derive(Debug)]
struct A {
data: Cell<i32>
}
#[derive(Debug)]
struct B<'a> {
a: &'a A
}
impl<'a> B<'a> {
fn new(reference: &'a A) -> B<'a> {
// Modify data
reference.data.set(reference.data.get() + 1);
B {
a: reference
}
}
}
fn main() {
let a1 = A{data: Cell::new(0)};
let b1 = B::new(&a1);
let b2 = B::new(&a1);
println!("{}", a1.data.get());
println!("{:?}", b1);
println!("{:?}", b2);
}
Upvotes: 4
Reputation: 4709
The borrow is not finished because you are keeping that reference alive in b1
. So the borrow is still alive when you try to do the same for b2
.
Maybe you just want this:
fn main() {
let mut a1 = A{data: 0};
let mut a2 = A{data: 0};
let b1 = B::new(&mut a1);
let b2 = B::new(&mut a2);
}
Upvotes: 0