Read-only field via getter, borrow issue

In the following code the field x should be read-only, achieved via a getter method. Furthermore, partial borrows of a are needed, an immutable one of x and a mutable one of y. That seems to be impossible because the getter borrows the whole struct.

The issue was also described here: Public “getter method” vs pub field, see partial borrow.

mod m {
    pub struct X(pub Vec<i32>);
    pub struct Y(pub Vec<i32>);
    pub struct A {x: X, pub y: Y}
    impl A {
        pub fn new() -> Self {Self{x: X(vec![]), y: Y(vec![])}}
        pub fn getx(&self) -> &X {&self.x}
    }
}

fn main() {
    let mut a = m::A::new();
    let x = a.getx();
    let y = &mut a.y;
    y.0.push(0);
    println!("{:?}",x.0)
}

As a workaround a struct or a tuple could be returned that splits the borrow:

pub fn getxy(&mut self) -> (&X, &mut Y) {(&self.x, &mut self.y)}

Are there any other options (apart from RefCell)?

This is the way to do it.


Another way is to do

mod m {
    pub ReadOnly<T>(T);

    impl<T> std::ops::Deref for ReadOnly<T> {
        type Target = T;

        fn deref(&self) -> &T {
            &self.0
        }
    }

    pub struct X(pub Vec<i32>);
    pub struct Y(pub Vec<i32>);
    pub struct A {
        pub x: ReadOnly<X>,
        pub y: Y
    }
    
    impl A {
        pub fn new() -> Self {Self{x: ReadOnly(X(vec![])), y: Y(vec![])}}
    }
}

fn main() {
    let mut a = m::A::new();
    let x = a.getx();
    let y = &mut a.y;
    y.0.push(0);
    println!("{:?}",x.0)
}

But this has the problem that if you have 2 m::As, you can swap their x fields, thus mutating the value.

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.