0

So I have some code like this:

use std::borrow::Borrow;
use std::cell::RefCell;
use std::collections::HashMap;
use std::ops::Index;
use std::rc::Rc;

struct Data {
    // ...
}

struct TableTreeNode {
    father: Option<Rc<RefCell<TableTreeNode>>>,
    table: HashMap<String, Data>,
}

impl Index<&str> for TableTreeNode {
    type Output = Data;

    fn index(&self, index: &str) -> &Self::Output {
        if self.table.contains_key(index) {
            self.table.index(index)
        } else {
            //recursively goes up
            let father: &RefCell<TableTreeNode> = self.father.as_ref().expect("not found");
            father.borrow().index(index)
        }
    }
}

It fails on compile:

error[E0515]: cannot return reference to temporary value
  --> xxx.rs:25:13
   |
25 |             father.borrow().index(index)
   |             ---------------^^^^^^^^^^^^^
   |             |
   |             returns a reference to data owned by the current function
   |             temporary value created here

I have no clue to solve this. How would a borrow from a RefCell could be a temporary variable? If I'm doing this wrong, what's the right way to implement these?

phioa
  • 11
  • 4
  • Does this answer your question? [How do I return a reference to something inside a RefCell without breaking encapsulation?](https://stackoverflow.com/questions/29401626/how-do-i-return-a-reference-to-something-inside-a-refcell-without-breaking-encap) – asynts Sep 02 '22 at 06:55

1 Answers1

0

Because RefCell::borrow() returns a Ref guard. This guard implements Deref, and when it is dropped it marks the RefCell as no longer borrowed.

Generally, you cannot hide a RefCell across API boundaries if you use it. You have to return a Ref<Something> or RefMut<Something> instead os &[mut] Something. And because the signature of Index is constant and expecting a reference, that means you cannot implement Index.

Chayim Friedman
  • 47,971
  • 5
  • 48
  • 77
  • You could also return `impl Deref` which handles both "naked" references and guards at the same time. – cdhowie Aug 25 '22 at 18:59