Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there any way I could use self from a method as an Rc<RefCell<T>>?

Tags:

rust

I have a struct (Foo) that has an Rc<RefCell<Bar>> field, Bar has a method that gets called by a Rc<RefCell<Bar>>, in that method it gets a reference to a Foo and I would like to set that Rc<RefCell<Bar>> in in that Foo to the Bar that called the method.

Consider the following code:

struct Foo {
    thing: Rc<RefCell<Bar>>,
}

struct Bar;

impl Foo {
    pub fn set_thing(&mut self, thing: Rc<RefCell<Bar>>) {
       self.thing = thing;
    }
}

impl Bar {
    pub fn something(&mut self) {
        // Things happen, I get a &mut to a Foo, and here I would like to use this Bar reference
        // as the argument needed in Foo::set_thing            
    }
}

// Somewhere else
// Bar::something is called from something like this:
let my_bar : Rc<RefCell<Bar>> = Rc::new(RefCell::new(Bar{}));
my_bar.borrow_mut().something();
// ^--- I'd like my_bar.clone() to be "thing" in the foo I get at Bar::something

Is the only way to do what I want to add another parameter to Bar::something accepting an Rc<RefCell<Bar>>? It feels redudant, when I'm already calling it from one.

    pub fn something(&mut self, rcSelf: Rc<RefCell<Bar>>) {
        foo.set_thing(rcSelf);
like image 228
GGalizzi Avatar asked Jan 08 '15 21:01

GGalizzi


People also ask

How does RefCell work?

The RefCell<T> keeps track of how many Ref<T> and RefMut<T> smart pointers are currently active. Every time we call borrow , the RefCell<T> increases its count of how many immutable borrows are active. When a Ref<T> value goes out of scope, the count of immutable borrows goes down by one.

Is RefCell send?

In fact, RefCell<T> is Send , at least when T: Send . You have a RefCell<&'a mut [T]> , which means that to make the RefCell Send all you need is to add a T: Send bound...

What is RefCell?

A RefCell is another way to change values without needing to declare mut . It means "reference cell", and is like a Cell but uses references instead of copies.


1 Answers

There are two main choices here:

  • Use a static method:

    impl Bar {
        pub fn something(self_: Rc<RefCell<Bar>>) {
            …
        }
    }
    
    Bar::something(my_bar)
    
  • Conceal the fact that you’re using Rc<RefCell<X>>, wrapping it in a new type with the single field Rc<RefCell<X>>; then other types can use this new type rather than Rc<RefCell<Bar>> and you can make this something method work with self. This may or may not be a good idea, depending on how you use it. Without further details it’s hard to say.

like image 90
Chris Morgan Avatar answered Oct 14 '22 17:10

Chris Morgan