2
votes

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?

2

2 Answers

3
votes

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);
}
0
votes

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);
}