尝试从封装在 RefCell 中的结构中借用 2 个字段时出错 [英] Error while trying to borrow 2 fields from a struct wrapped in RefCell
问题描述
我有一个结构体,其中包含数据和最终用于写入数据的编写器.该结构包含在 RefCell
中.这是一个小复制:
I have a struct which contains both data and a writer which will eventually be used to write the data. The struct is wrapped in a RefCell
. Here's a small reproduction:
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 吗?
Is there a different API I should use?
推荐答案
您可以手动调用 DerefMut
然后保存结果引用:
You can manually invoke DerefMut
and then save the resulting reference:
fn write(s: RefCell<S>) {
let mut mut_s = s.borrow_mut();
let mut tmp = &mut *mut_s; // Here
let str = &tmp.data.string;
tmp.writer.write(str.as_bytes());
}
或在一行中:
fn write(s: RefCell<S>) {
let mut_s = &mut *s.borrow_mut(); // Here
let str = &mut_s.data.string;
mut_s.writer.write(str.as_bytes());
}
问题在于 borrow_mut
不直接返回你的结构——它返回一个 RefMut
.通常,这是透明的,因为该结构实现了 Deref
和 DerefMut
,因此对其调用的任何方法都会传递给基础类型.伪扩展代码如下所示:
The problem is that borrow_mut
doesn't return your struct directly — it returns a RefMut
. Normally, this is transparent as this struct implements Deref
and DerefMut
, so any methods called on it are passed to the underlying type. The pseudo-expanded 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 不跟踪跨函数调用的字段级借用(即使对于 Deref::deref
或 DerefMut::deref_mut
).这会导致您的错误,因为在从之前的 Deref::deref
借用期间,需要调用 deref_mut
方法.
Rust doesn't track field-level borrows across function calls (even for Deref::deref
or DerefMut::deref_mut
). This causes your error, as the deref_mut
method would need to be called during the outstanding borrow from the previous Deref::deref
.
具有显式借用的扩展版本如下所示,只需调用一次 Deref::deref_mut
:
The expanded version with the explicit borrow looks like this, 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 borrows from that temporary value are disjoint.
注意这个问题不是RefCell
独有的!任何实现 DerefMut
的类型都可以遇到同样的问题.以下是标准库中的一些内容:
Note that this problem isn't unique to RefCell
! Any type that implements DerefMut
can experience the same problem. Here's some from the standard library:
Box
MutexGuard
(fromMutex
)PeekMut
(fromBinaryHeap
)RwLockWriteGuard
(fromRwLock
)String
Vec
Pin
这篇关于尝试从封装在 RefCell 中的结构中借用 2 个字段时出错的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!