【发布时间】:2023-03-25 09:13:02
【问题描述】:
我有一个具有内部可变性的结构。
use std::cell::RefCell;
struct MutableInterior {
hide_me: i32,
vec: Vec<i32>,
}
struct Foo {
//although not used in this particular snippet,
//the motivating problem uses interior mutability
//via RefCell.
interior: RefCell<MutableInterior>,
}
impl Foo {
pub fn get_items(&self) -> &Vec<i32> {
&self.interior.borrow().vec
}
}
fn main() {
let f = Foo {
interior: RefCell::new(MutableInterior {
vec: Vec::new(),
hide_me: 2,
}),
};
let borrowed_f = &f;
let items = borrowed_f.get_items();
}
产生错误:
error[E0597]: borrowed value does not live long enough
--> src/main.rs:16:10
|
16 | &self.interior.borrow().vec
| ^^^^^^^^^^^^^^^^^^^^^^ temporary value does not live long enough
17 | }
| - temporary value only lives until here
|
note: borrowed value must be valid for the anonymous lifetime #1 defined on the method body at 15:5...
--> src/main.rs:15:5
|
15 | / pub fn get_items(&self) -> &Vec<i32> {
16 | | &self.interior.borrow().vec
17 | | }
| |_____^
问题是我不能在Foo 上拥有一个返回借用vec 的函数,因为借用的vec 仅在Ref 的生命周期内有效,但Ref 可以使用立即超出范围。
我认为Ref 必须坚持because:
RefCell<T>使用 Rust 的生命周期来实现“动态借用”,这是一个可以声明对内部值的临时、独占、可变访问的过程。RefCell<T>s 的借用是在“运行时”跟踪的,这与 Rust 的本地引用类型不同,后者在编译时完全静态跟踪。因为RefCell<T>借用是动态的,所以可以尝试借用一个已经可变借用的值;发生这种情况时会导致任务恐慌。
现在我可以写一个这样的函数来返回整个内部:
pub fn get_mutable_interior(&self) -> std::cell::Ref<MutableInterior>;
但是,这可能会向Foo 公开真正私有的实现细节的字段(在此示例中为MutableInterior.hide_me)。
理想情况下,我只想公开vec 本身,可能带有一个守卫来实现动态借用行为。这样来电者就不必知道hide_me。
【问题讨论】:
标签: rust encapsulation contravariance mutability interior-mutability