Looking through the documentation for std::cell::Cell, I don't see anywhere how I can retrieve a non-mutable reference to inner data. There is only the get_mut
method: https://doc.rust-lang.org/std/cell/struct.Cell.html#method.get_mut
I don't want to use this function because I want to have &self
instead of &self mut
.
I found an alternative solution of taking the raw pointer:
use std::cell::Cell;
struct DbObject {
key: Cell<String>,
data: String
}
impl DbObject {
pub fn new(data: String) -> Self {
Self {
key: Cell::new("some_uuid".into()),
data,
}
}
pub fn assert_key(&self) -> &str {
// setup key in the future if is empty...
let key = self.key.as_ptr();
unsafe {
let inner = key.as_ref().unwrap();
return inner;
}
}
}
fn main() {
let obj = DbObject::new("some data...".into());
let key = obj.assert_key();
println!("Key: {}", key);
}
Is there any way to do this without using unsafe? If not, perhaps RefCell will be more practical here?
Thank you for help!
First of, if you have a &mut T
, you can trivially get a &T
out of it. So you can use get_mut
to get &T
.
But to get a &mut T
from a Cell<T>
you need that cell to be mutable, as get_mut
takes a &mut self
parameter. And this is by design the only way to get a reference to the inner object of a cell.
By requiring the use of a &mut self
method to get a reference out of a cell, you make it possible to check for exclusive access at compile time with the borrow checker. Remember that a cell enables interior mutability, and has a method set(&self, val: T)
, that is, a method that can modify the value of a non-mut
binding! If there was a get(&self) -> &T
method, the borrow checker could not ensure that you do not hold a reference to the inner object while setting the object, which would not be safe.
TL;DR: By design, you can't get a &T
out of a non-mut
Cell<T>
. Use get_mut
(which requires a mut
cell), or set
/replace
(which work on a non-mut
cell). If this is not acceptable, then consider using RefCell
, which can get you a &T
out of a non-mut instance, at some runtime cost.