У меня есть структура, которая имеет внутреннюю изменчивость.
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
должен стоять, потому что:
RefCell<T>
использует времена жизни Rust для реализации "динамического заимствования", процесс, при котором можно требовать временный, исключительный, изменяемый доступ к внутреннему значению.RefCell<T>
дляRefCell<T>
отслеживаются "во время выполнения", в отличие от стандартных ссылочных типов Rust, которые полностью отслеживаются статически во время компиляции. Так какRefCell<T>
занимает динамические данные, можно попытаться заимствовать значение, которое уже было заимствовано; когда это происходит, это приводит к панике задач.
Теперь я мог бы написать такую функцию, которая возвращает весь интерьер:
pub fn get_mutable_interior(&self) -> std::cell::Ref<MutableInterior>;
Однако это потенциально предоставляет поля (MutableInterior.hide_me
в этом примере), которые действительно являются MutableInterior.hide_me
реализации для Foo
.
В идеале я просто хочу разоблачить сам vec
, потенциально с защитой для реализации поведения динамического заимствования. Затем вызывающим абонентам не нужно узнавать о hide_me
.