I have a struct Region which contains [Option<Rc<RefCell<Region>>>; 2] as its subregions and Option<Weak<RefCell<Region>>> as its container. I am writing a method to insert a new Region between self and self.container, which requires me to clone the Rc to self to include in the newly created Region as one of its subregions. When self.container is Some this is possible because I can walk up to the container and then clone its subregion that matches self, but when self has None as its container, I do not know how to get a clone of the Rc of self from the &mut self that is passed into the method.
Here is some code to make it clearer.
struct Region {
subregions: [Option<Rc<RefCell<Region>>>; 2],
container: Option<Weak<RefCell<Region>>>,
}
impl Region {
fn clone_from_container(&self) -> Option<Rc<RefCell<Region>>> {
Some(Rc::clone(&self.container
.as_ref()?
.upgrade()
.unwrap()
.borrow()
.subregions[self.from()]
.as_ref()
.unwrap()))
}
pub fn insert_above(&mut self) -> Rc<RefCell<Region>> {
let new = Rc::new(RefCell::new(Region {
subregion: [self.clone_from_container(),None],
container: self.container.clone(),
}));
self.replace(new.clone());
self.container = Some(Rc::downgrade(&new.clone()));
new
}
}
In my actual code there are a few more functions, but these are just aliases for long method chains to unbox the Rcs and RefCells to allow me to actually get at the data. I've tried to keep it to the important details only.
The methods I've excluded, Region::replace and Region::from are pretty simple and their implementation don't matter. replace walks up to the container and replaces the reference to self with the new region (very similar to clone_from_container but to mutate the Region), and from simply finds the index of the Region within its container's subregions (0 or 1)
When setting the subregion of new within, I would like to be able to say something like self.clone_from_container().or(Rc::clone(self)), but obviously this isn't possible given the type that self is passed as.
I figure it may just be necessary to have this be a static factory function, rather than an instance method, so we can pass self with type Rc<RefCell<Region>>, but I also thought it may be possible to use Rc::new_cyclic; however, that function is somewhat confusing and I'm not quite sure how to employ it.
To simplify, I'm gonna say
Rc<Region>instead ofRc<RefCell<Region>>If I understood correctly, this is your situation:
And you have a method such as:
This is not possible, because
Regiondoesn't know that it is inside anRc. You have to somehow tell it that it is inside anRc.One possible solution is to not use
self. For example:Another option, as PitaJ suggested, is to make a trait for
Rc<Region>, in that case,selfwould beRc<Region>, so you'd have access toRc.