Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why can I not call borrow_mut() after indexing into an immutable Vec<RefCell>?

Tags:

rust

Let's try to compile this code:

use std::cell::RefCell;

struct Foo {
    v: Vec<RefCell<u8>>,
}

impl Foo {
    fn f(&self, i: usize) {
        let t = &mut *self.v[i].borrow_mut();
        //let t = &mut *{self.v[i].borrow_mut()}; //compiled ok
    }
}

fn main() {}

Compilation error:

error[E0596]: cannot borrow field `self.v` of immutable binding as mutable
 --> src/main.rs:9:23
  |
8 |     fn f(&self, i: usize) {
  |          ----- use `&mut self` here to make mutable
9 |         let t = &mut *self.v[i].borrow_mut();
  |                       ^^^^^^ cannot mutably borrow field of immutable binding

Why does this code require adding &mut self to function signature in order to compile?

like image 719
chabapok Avatar asked Oct 25 '18 12:10

chabapok


2 Answers

This is a known issue where IndexMut is sometimes selected when Index should actually be used.

Your workaround of using {} is reasonable, but you can also use Index explicitly:

use std::cell::RefCell;

fn f(v: Vec<RefCell<u8>>) {
    use std::ops::Index;
    let _t = &mut v.index(0).borrow_mut();
}

fn main() {}

See also:

  • Why does a mutable borrow of a closure through DerefMut not work?
  • How to use `BorrowMut` contained within `RefCell`?
like image 112
Shepmaster Avatar answered Dec 30 '22 17:12

Shepmaster


Another workaround is to explicitly call RefCell::borrow_mut(&v[0]).

like image 34
Alexander Irbis Avatar answered Dec 30 '22 17:12

Alexander Irbis