Any reference obtained through the interior mutability pattern, be it Rc<RefCell<T>>
or Arc<RwLock<T>>
, will have to be dropped as the enclosing function returns. When you want to use this reference to return a reference to some data that this RefCell
or RwLock
protects, it is not allowed.
I think it is right to NOT ALLOW it: because I am using interior mutability, any reference associated with the "interior" should be delegated to the runtime checker, and thus a pure reference as &T
should not be exposed to the outside.
However, I could not figure out a good alternative that serves the same purpose, other than wrap the underlying data with Rc<RefCell<T>>
as well.
Code that demonstrates the issue:
use std::string::String;
use std::sync::{Arc, RwLock};
struct MyStruct {
data: MyData,
}
struct MyData {
val: String,
}
fn main() {
let my_struct = MyStruct {
data: MyData {
val: String::from("hi"),
},
};
let obj = Arc::new(RwLock::new(my_struct));
let data = get_data_ref(&obj);
println!("{}", data);
}
fn get_data_ref(obj: &Arc<RwLock<MyStruct>>) -> &String {
let obj = Arc::clone(obj);
let data = obj.read().unwrap(); //data is created
data.get_data()
} //data dropped here, thus lives not long enough.
impl MyStruct {
fn get_data(&self) -> &String {
self.data.get_val()
}
}
impl MyData {
fn get_val(&self) -> &String {
&self.val
}
}