2

How can I return a reference to something from inside a shared pointer (in this case Rc<RefCell<_>>)? In the example below, I show how it can be done with just a regular mutable reference to self, but if it becomes a shared pointer instead, the compiler gets angry that the return type has a missing lifetime specifier.

error[E0106]: missing lifetime specifier
  --> src/main.rs:19:60
   |
19 |     fn add_to_shared(me: Rc<RefCell<Thing>>, item: i32) -> &i32 {
   |                                                            ^ expected named lifetime parameter
   |
   = help: this function's return type contains a borrowed value with an elided lifetime, but the lifetime cannot be derived from the arguments
help: consider using the `'static` lifetime
   |
19 |     fn add_to_shared(me: Rc<RefCell<Thing>>, item: i32) -> &'static i32 {
   |                                                            ^^^^^^^^
use std::cell::RefCell;
use std::rc::Rc;

struct Thing {
    items: Vec<i32>,
}

impl Thing {    
    fn new() -> Self {
        Thing { items: Vec::new() }
    }

    fn add_to_self(&mut self, item: i32) -> &i32 {
        self.items.push(item);
        self.items.last().unwrap()
    }

    // does not compile
    fn add_to_shared(me: Rc<RefCell<Thing>>, item: i32) -> &i32 {
        me.borrow().items.push(item);
        me.borrow().items.last().unwrap()
    }
}

fn main() {
    let mut thing = Thing::new();
    println!("{}", thing.add_to_self(10));

    let mut rc = Rc::new(RefCell::new(Thing::new()));
    println!("{}", rc.add_to_shared(20));
}

Why do I want to do this? I have a program that builds a tree-like structure with multiple ownership. One of the associated methods takes two nodes of the tree (each shared pointers) and bundles them together into another part of the tree. Each method returns a reference to the newly created node so that it can be conveniently logged out (see the example).

I was thinking I'd need to use lifetime annotations to get this to work, but I have not been able to find out how do apply this concept to the interior of a Rc<RefCell<_>> type.

Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
PersonWithName
  • 848
  • 2
  • 13
  • 19
  • 3
    TL;DR the duplicates: you **can't**. The entire point of `RefCell` is that the lifetime is tied to the value returned from `borrow` and not to the `RefCell` itself. – Shepmaster Sep 23 '20 at 14:56

1 Answers1

1

I think the problem here is that Rust knows how long self lives, but is not able to figure out how long Rc<RefCell<_>> exists. Do you need to return i32 references? If you would return just i32, the value would be copied and you would not have a reference into a struct that might not exists long enough.

phil
  • 1,377
  • 2
  • 9
  • 14