我正在使用ratatui库来使用rustc 1.77.2制作一个程序。
我有以下代码:
self.terminal().draw(|frame| self.render_frame(frame))?;
其中
terminal()
是保存接受 &self
的终端实例的结构体的 getter,draw 是绘制到屏幕的ratatui 方法。 self.render_frame
需要 &mut self。
如果
terminal()
返回 &mut Terminal
,则会导致借用错误,因此 terminal()
返回 RefMut<Terminal>
,而 Self
有一个 terminal
字段,其中包含 RefCell<Terminal
,并调用 self.terminal.borrow_mut()
作为 terminal()
的实施。
我的逻辑是,由于
terminal()
返回 refmut
,一个自有值,借用检查器不会考虑该值,并且只要 terminal()
不用于 self.render_frame()
中,就不会有问题。
然而,事实并非如此,因为我收到以下错误:
error[E0502]: cannot borrow `self` as mutable because it is also borrowed as immutable
--> src/tui.rs:75:38
|
75 | self.terminal().draw(|frame| self.render_frame(frame))?;
| --------------- ^^^^^^^ ---- - ... and the immutable borrow might be used here, when that temporary is dropped and runs the destructor for type `RefMut<'_, ratatui::Terminal<ratatui::backend::CrosstermBackend<Stdout>>>`
| | | |
| | | second borrow occurs due to use of `self` in closure
| | mutable borrow occurs here
| immutable borrow occurs here
| a temporary with access to the immutable borrow is created here ...
令我困惑的是,为什么借用检查器会考虑
RefMut
,而在运行时执行的这些规则表面上就是 RefCell
的全部要点。
具体来说,我有兴趣知道我对
RefMut
/RefCell
的使用是如何不正确的,以及如何修复它;因为我在使用 Refcell
时找不到任何有关借用检查器错误的信息。
令我困惑的是,为什么借用检查器会考虑
,而在运行时执行的这些规则表面上就是RefMut
的全部要点。RefCell
这是正确的,但您仍然需要共享借用才能使用它。像RefCell
这样的内部可变性类型给你带来的
唯一的事情是通过共享引用进行变异的能力。对于
RefCell
,这允许您从 &mut T
获得 &RefCell<T>
。换句话说,这允许您将共享借用 (&
)“升级”为独占借用 (&mut
),但要做到这一点您仍然需要 RefCell
的共享借用。
看起来
render_frame
需要 &mut self
,这会导致问题:RefMut
借用于 self
,但 render_frame
想要一个 独占 引用。
在看不到其余代码的情况下,很难确切地说出如何解决这个问题。一种选择是让
render_frame
采用 &self
而不是 &mut self
,这在本例中是允许的。但是,这样做可能需要您使更多此类部分使用内部可变性。
听起来很像你是从面向对象的角度来解决这个问题的,而这样的设计在 Rust 中往往效果不佳。也许这里
self
代表的任何类型都做得太多,需要分开。