Best way to hide borrow_mut

Hello,

For now, my struct looks like this:

pub struct A {
pub b:Rc<RefCell<B>>
}
pub struct B {
field:String
}

impl B {
pub fn update(&mut self,text:String){
self.field=text;
}
}

For now, I use it like the following to move it into a closure:

let a = A {
        b: Rc::new(RefCell::new(B {
            field: "hello".to_string(),
        })),
    };
    let clone = a.b.clone();
    clone.borrow_mut().update("updated".to_string());

What I would like is to remove borrow_mut and update the field from my update function like this:

let clone = a.b.clone();
clone.update("updated".to_string());

Thank you in advance for your help.

2 Likes

Note that a.b.clone() is only incrementing the Rc count -- is that what you intend? This is still pointing to the shared RefCell, so it does need the borrow_mut intermediate.

1 Like

I'd like:

pub struct A {
pub b:B
}

where B handles the borrow_mut inside update function.

Is there a clever way to manage that instead of giving access to Rc<RefCell ?

Then you can define your B with Rc<RefCell<_>> for private fields, or perhaps even an entire InnerB type.

I didn't realize before that this was in the internals forum, but this kind of question is more suited for users.rust-lang.org, and you'll probably get more active responses there. If you get some concrete idea of what could be added or changed in Rust itself, then that would be welcome back here.

5 Likes

You are right. Sorry, I posted to the wrong forum... But what about something like this then:

pub struct A {
pub b:B
}
pub struct B {
field:String
}

impl B {
pub fn update(Rc<RefCell<&mut self>>,text:String){
self.field=text;
}
}

or:

pub struct A {
pub b:B
}
pub struct B {
field:String
}

impl B {
pub(clone) fn update(&mut self,text:String){
self.field=text;
}
}

Note pub(clone) or pub fn update(Rc<RefCell<&mut self>> difference to show the function only when the struct is cloned.

What is your reason for not wanting the .borrow_mut? Do you just not want to type it?

One solution would be to create a newtype for Rc<RefCell<B>>, and make a getter on A that returns that instead of the Rc directly. Like this (I renamed your B to BInner):

pub struct A {
    b: Rc<RefCell<BInner>>,
}
impl A {
    pub fn b(&self) -> B {
        B(self.b.clone())
    }
}
struct BInner {
    field: String,
}

pub struct B(Rc<RefCell<BInner>>);

impl B {
    pub fn update(&self, text: String) {
        self.0.borrow_mut().field = text;
    }
}
1 Like

I asked to the users forum because I posted to the wrong forum. Sorry...

And I get the answer.

Thank you for your help.