如何将引用 return 引用到 Rc<RefCell<>> 函数参数中?
How to return a reference into a Rc<RefCell<>> function argument?
这是从我正在编写的解释器中获取的最小可重现错误。据我了解,我应该能够 return 对 RefCell 中结构字段的引用,因为 RefCell 具有足够的生命周期。但是,编译器告诉我我不能 return 对当前函数拥有的值的引用,坦率地说这让我感到困惑。
use std::cell::RefCell;
use std::collections::HashMap;
use std::rc::Rc;
#[derive(Debug)]
enum Value {
Number,
String,
}
struct Object {
pub properties: HashMap<String, Value>,
}
impl Object {
pub fn get_property(&mut self, name: &str) -> Option<&mut Value> {
self.properties.get_mut(name)
}
}
fn get_property(global_object_rcc: Rc<RefCell<Object>>, name: &str) -> Option<&mut Value> {
// Rust cannot verify that this Rc isn't the last Rc that just got moved into this function?
global_object_rcc.borrow_mut().get_property(name)
}
fn main() {
// Construct global object
let mut global_object = Object {
properties: HashMap::new(),
};
// Give it a property
global_object
.properties
.insert("Test".to_owned(), Value::Number);
// Put it in a Rc<RefCell> (rcc) for sharing
let global_object_rcc = Rc::new(RefCell::new(global_object));
// Get a reference to its property, should be valid because the reference only needs to live
// as long as the global_object
let property = get_property(global_object_rcc, "Test");
dbg!(&property);
}
这是我收到的错误消息:
error[E0515]: cannot return value referencing temporary value
--> src\main.rs:23:5
|
23 | global_object_rcc.borrow_mut().get_property(name)
| ------------------------------^^^^^^^^^^^^^^^^^^^
| |
| returns a value referencing data owned by the current function
| temporary value created here
这行不通。 RefCell
return 上的 borrow_mut()
是一个 RefMut
,它管理可变借用并确保在它存在时没有其他借用。然后调用 get_property
借用 RefMut
(隐含地通过 deref 和 &mut self
)和 returns 一个引用(&mut Value
)与方法的接收者(&mut self
)。所以 &mut Value
的生命周期取决于 RefMut
是否还活着;但它在 get_property
return 时被销毁,引用无效。
RefCell
(就此而言任何 Cell
)的全部要点是借用无法“逃脱”。您可以尝试使用 &mut Value
调用的闭包;或者你可以 return 给调用者 RefMut
,缺点是你的类型不能排除调用者保留它,防止将来借用。
调用 .borrow_mut()
时,临时借用的引用被 returned,然后可以取消引用以改变内部数据。您获得的引用将从 borrow_mut()
return 秒到 .get_property(name)
return 秒存在,这个时间不足以让引用在函数结束后继续存在.
这与Rc<RefCell<Object>>
的生命周期不同,它实际上是移入被调用的函数中,并且会在函数returns后被丢弃(但是Rc只会减少refcount,并且只会如果引用计数为 0,则丢弃内部数据)。不能将引用的生命周期 link 编辑为 Rc<>
内的内部数据的生命周期,因为该生命周期直到运行时才知道,基于引用计数。
如果 .borrow_mut()
调用发生在 fn get_property()
之外,并且您将 &mut Object
传递给 fn get_property()
,这样它 returns Option<&mut Value
,然后您可以使用生命周期变量 link 输入引用生命周期到输出引用生命周期,这将绕过编译器错误:
fn get_property<'a>(global_object_rcc: &'a mut Object, name: &str) -> Option<&'a mut Value> { ... }
但从这个示例的外观来看,这可能不是您想要做的。
制作根据需要改变数据的函数可能会更好,这样您就只有 .borrow_mut()
借用的引用 return 尽可能短的时间(只有很长时间足以改变函数内的数据,以及 return 当您不再需要引用时)。如果您尝试多次借用引用,则长时间保留 .borrow_mut()
引用会导致恐慌!()。
这是从我正在编写的解释器中获取的最小可重现错误。据我了解,我应该能够 return 对 RefCell 中结构字段的引用,因为 RefCell 具有足够的生命周期。但是,编译器告诉我我不能 return 对当前函数拥有的值的引用,坦率地说这让我感到困惑。
use std::cell::RefCell;
use std::collections::HashMap;
use std::rc::Rc;
#[derive(Debug)]
enum Value {
Number,
String,
}
struct Object {
pub properties: HashMap<String, Value>,
}
impl Object {
pub fn get_property(&mut self, name: &str) -> Option<&mut Value> {
self.properties.get_mut(name)
}
}
fn get_property(global_object_rcc: Rc<RefCell<Object>>, name: &str) -> Option<&mut Value> {
// Rust cannot verify that this Rc isn't the last Rc that just got moved into this function?
global_object_rcc.borrow_mut().get_property(name)
}
fn main() {
// Construct global object
let mut global_object = Object {
properties: HashMap::new(),
};
// Give it a property
global_object
.properties
.insert("Test".to_owned(), Value::Number);
// Put it in a Rc<RefCell> (rcc) for sharing
let global_object_rcc = Rc::new(RefCell::new(global_object));
// Get a reference to its property, should be valid because the reference only needs to live
// as long as the global_object
let property = get_property(global_object_rcc, "Test");
dbg!(&property);
}
这是我收到的错误消息:
error[E0515]: cannot return value referencing temporary value
--> src\main.rs:23:5
|
23 | global_object_rcc.borrow_mut().get_property(name)
| ------------------------------^^^^^^^^^^^^^^^^^^^
| |
| returns a value referencing data owned by the current function
| temporary value created here
这行不通。 RefCell
return 上的 borrow_mut()
是一个 RefMut
,它管理可变借用并确保在它存在时没有其他借用。然后调用 get_property
借用 RefMut
(隐含地通过 deref 和 &mut self
)和 returns 一个引用(&mut Value
)与方法的接收者(&mut self
)。所以 &mut Value
的生命周期取决于 RefMut
是否还活着;但它在 get_property
return 时被销毁,引用无效。
RefCell
(就此而言任何 Cell
)的全部要点是借用无法“逃脱”。您可以尝试使用 &mut Value
调用的闭包;或者你可以 return 给调用者 RefMut
,缺点是你的类型不能排除调用者保留它,防止将来借用。
调用 .borrow_mut()
时,临时借用的引用被 returned,然后可以取消引用以改变内部数据。您获得的引用将从 borrow_mut()
return 秒到 .get_property(name)
return 秒存在,这个时间不足以让引用在函数结束后继续存在.
这与Rc<RefCell<Object>>
的生命周期不同,它实际上是移入被调用的函数中,并且会在函数returns后被丢弃(但是Rc只会减少refcount,并且只会如果引用计数为 0,则丢弃内部数据)。不能将引用的生命周期 link 编辑为 Rc<>
内的内部数据的生命周期,因为该生命周期直到运行时才知道,基于引用计数。
如果 .borrow_mut()
调用发生在 fn get_property()
之外,并且您将 &mut Object
传递给 fn get_property()
,这样它 returns Option<&mut Value
,然后您可以使用生命周期变量 link 输入引用生命周期到输出引用生命周期,这将绕过编译器错误:
fn get_property<'a>(global_object_rcc: &'a mut Object, name: &str) -> Option<&'a mut Value> { ... }
但从这个示例的外观来看,这可能不是您想要做的。
制作根据需要改变数据的函数可能会更好,这样您就只有 .borrow_mut()
借用的引用 return 尽可能短的时间(只有很长时间足以改变函数内的数据,以及 return 当您不再需要引用时)。如果您尝试多次借用引用,则长时间保留 .borrow_mut()
引用会导致恐慌!()。