You can manually call DerefMut and then save the resulting link:
fn write(s: RefCell<S>) { let mut mut_s = s.borrow_mut(); let mut tmp = &mut *mut_s; let str = &tmp.data.string; tmp.writer.write(str.as_bytes()); }
The problem is that borrow_mut does not return your structure directly - it returns RefMut . This is usually transparent, since this structure implements Deref and DerefMut , so any methods it DerefMut are passed to the base type. The pseudo-extended code looks something like this:
use std::cell::RefMut; use std::ops::{Deref, DerefMut}; fn write(s: RefCell<S>) { let mut mut_s: RefMut<S> = s.borrow_mut(); let str = &Deref::deref(&mut_s).data.string; DerefMut::deref_mut(&mut mut_s).writer.write(str.as_bytes()); }
Rust does not track field-level borrowing between function calls (even for Deref::deref or DerefMut::deref_mut ). This leads to your error, since the deref_mut method deref_mut have to be called during Deref::deref borrowing from the previous Deref::deref .
An extended version with explicit borrowing is as follows, with a single call to Deref::deref_mut :
use std::cell::RefMut; use std::ops::DerefMut; fn write(s: RefCell<S>) { let mut mut_s: RefMut<S> = s.borrow_mut(); let tmp: &mut S = DerefMut::deref_mut(&mut mut_s); let str = &tmp.data.string; tmp.writer.write(str.as_bytes()); }
The compiler can then track that the two borrowings from this temporary value do not intersect.
Please note that this problem is not unique to RefCell ! Any type that implements DerefMut may run into the same problem. Here are some of the standard library:
source share