Borrowing from a nested RefCell

You can make your own ref type that allows you to ask for a Ref<u8> like this:

impl OuterStruct {
    pub fn borrow_inner_value<'a>(&'a self) -> MyDoubleRef<'a> {
        let r = self.inner_struct.borrow();
        MyDoubleRef {
            r: Ref::map(r, |r| &r.the_value)
        }
    }
}

pub struct MyDoubleRef<'a> {
    r: Ref<'a, RefCell<u8>>,
}
impl<'a> MyDoubleRef<'a> {
    pub fn borrow<'b>(&'b self) -> Ref<'b, u8> {
        self.r.borrow()
    }
}

playground

The reason that a Ref<'a, Ref<'a, u8>> is not possible is that the lifetime annotation simply says to the compiler "This value cannot outlive the lifetime 'a". In particular, it does not say that "This value must live exactly as long as 'a". It is allowed to not live as long as that lifetime.

So if you compare Ref<'a, Ref<'a, u8>> to Ref<'a, u8>, there's nothing here that says that the second must live shorter than the first. They have a shared deadline they can't outlive, but which one lives for the longest is not determined by those lifetimes.

The reason these other approaches work is that the inner Ref<'b, u8> you can obtain does not have the same lifetime annotation as the outer Ref. The lifetime annotation on Ref<'b, u8> is the lifetime of a borrow of the outer Ref, so this Ref<'b, u8> cannot outlive that borrow of the outer Ref, which is what makes it sound.

3 Likes