Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Struct with immutable reference to other struct

Tags:

rust

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?

like image 407
Stefan Pfeifer Avatar asked May 19 '26 10:05

Stefan Pfeifer


1 Answers

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);
}
like image 189
tafia Avatar answered May 21 '26 05:05

tafia



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!