1

I'm trying to implement the Index method for a struct with interior mutability:

pub struct FooVec {
    foo: RefCell<Vec<i32>>
}

impl Index<usize> for FooVec {
    type Output = i32;

    fn index(&self, index: usize) -> &Self::Output {
        self.foo.borrow().index(index)
    }
}

However, this does not compile due to:

error[E0515]: cannot return value referencing temporary value
 --> src\lacc\expr.rs:9:9
  |
9 |         self.foo.borrow().index(index)
  |         -----------------^^^^^^^^^^^^^
  |         |
  |         returns a value referencing data owned by the current function
  |         temporary value created here

My solution would be to return a reference of the vector in the RefCell. But the only method I find which does that is get_mut() and for the Index trait I need to return an immutable reference...

I would appreciate any suggestions on how to deal with this.

Adam
  • 743
  • 1
  • 6
  • 11

1 Answers1

3

You can't implement Index: the Index trait requires returning a reference, this means that it has to return something which is attached to and trivially accessible from the object.

That's not the case here as you need to go through RefCell::borrow, which essentially functions as if it were creating a value from scratch (because it only hands out access through a Ref "lock guard").

I would appreciate any suggestions on how to deal with this.

Do something else. Index is not an option. Given the types involved I'd suggest just implementing a get method which returns an Option<i32>, something along those lines.

Masklinn
  • 34,759
  • 3
  • 38
  • 57
  • Thanks, I was afraid of that. I don't understand why RefCell implements get_mut() and not get() though.. – Adam Mar 06 '21 at 13:16
  • 1
    @Adam because that could not uphold Rust's aliasing guarantees: `get_mut()` requires a mutable reference, so we statically know there's only one reference to the `RefCell` and nobody has any way to get an other one concurrently through `borrow` or `borrow_mut`. However since `get()` would only require an immutable reference, we could concurrently call `borrow_mut()`, and the `RefCell` would have no way to know that there are outstanding references, therefore we'd concurrently have a mutable reference and a non-zero number of immutable references, which is absolutely verboten. – Masklinn Mar 06 '21 at 14:47
  • 1
    Also you may want to take a look at owning-ref, it's rather complicated to use but the point is to carry references and their owners together, so that might work out for you. – Masklinn Mar 06 '21 at 14:49