我有一个结构,其中包含数据和最终将用于写入数据的编写器 . 结构包含在 RefCell
中 . 这是一个小的复制品:
use std::cell::RefCell;
use std::io::Write;
struct Data {
string: String,
}
struct S {
data: Data,
writer: Vec<u8>,
}
fn write(s: RefCell<S>) {
let mut mut_s = s.borrow_mut();
let str = &mut_s.data.string;
mut_s.writer.write(str.as_bytes());
}
编译器很生气:
error[E0502]: cannot borrow `mut_s` as mutable because it is also borrowed as immutable
--> src\main.rs:16:5
|
15 | let str = &mut_s.data.string;
| ----- immutable borrow occurs here
16 | mut_s.writer.write(str.as_bytes());
| ^^^^^ mutable borrow occurs here
17 | }
| - immutable borrow ends here
我应该使用不同的API吗?
1 回答
您可以手动调用
DerefMut
,然后保存生成的引用:或者在一行中:
问题是borrow_mut不直接返回你的结构 - 它返回一个RefMut . 通常,这是透明的,因为此结构实现Deref和DerefMut,因此调用它的任何方法都将传递给基础类型 . pseduo扩展代码看起来像这样:
Rust不会跟踪函数调用的字段级借位(即使是
Deref::deref
或DerefMut::deref_mut
) . 这会导致您的错误,因为在前一个Deref::deref
的未完成借用期间需要调用deref_mut
方法 .具有显式借用的扩展版本看起来像这样,只需调用
Deref::deref_mut
:然后,编译器可以跟踪该临时值的两个借位是不相交的 .
注意这个问题 isn't unique 到
RefCell
!任何实现DerefMut的类型都可能遇到同样的问题 . 以下是标准库中的一些内容:Box
MutexGuard
(来自Mutex)PeekMut
(来自BinaryHeap)RwLockWriteGuard
(来自RwLock)String
Vec
Pin