【发布时间】:2018-07-15 15:01:00
【问题描述】:
有时我有一个 struct 包含一个包装在 RefCell 中的值,我想借用该值,但我不想让访问器函数的签名依赖于内部实现.为了使其工作,我需要将引用返回为 Ref<T> 而不是 &T。
例如,如果这是我的结构:
use std::cell::RefCell;
pub struct Outer<T> {
inner: RefCell<T>,
}
我可以这样写一个访问器:
use std::cell::Ref;
impl<T> Outer<T> {
fn get_inner_ref(&self) -> Ref<T> {
self.inner.borrow()
}
}
这很好用。我可以这样使用它:
fn main() {
let outer = Outer { inner: RefCell::new(String::from("hi")) };
let inner: &str = &outer.get_inner_ref();
println!("inner value = {:?}", inner);
}
但是,这会将Ref 公开为公共 API 的一部分,这会使以后更难更改内部结构,而不会破坏向后兼容性。
如果我尝试更改签名以返回 &T — &Ref<T> 可以强制返回 — 那么我会得到终身错误:
impl<T> Outer<T> {
fn get_inner_ref(&self) -> &T {
&self.inner.borrow()
}
}
错误是:
error[E0597]: borrowed value does not live long enough
--> src/main.rs:16:10
|
16 | &self.inner.borrow()
| ^^^^^^^^^^^^^^^^^^^ 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 | / fn get_inner_ref(&self) -> &T {
16 | | &self.inner.borrow()
17 | | }
| |_____^
似乎没有办法解决这个问题,因为错误消息是正确的。该代码试图引用Ref<T>,它只持续与函数调用一样长。为了完成这项工作,我必须通过返回它来移除 Ref<T> 本身——就像在上面的原始代码中一样——而不是对它进行新的引用。
有an answer to How do I return a reference to something inside a RefCell without breaking encapsulation? 可以从技术上解决这个问题,但它是一个更专业的案例(仅获取RefCell 中的一部分值),对于这种更简单的情况,解决方案似乎过于复杂。
【问题讨论】:
标签: generics reference rust borrow-checker