I am getting an error lifetime may not live long enough returning this value requires that 1 must outlive 2
I want to return the reference to one of the requested properties from StableStates, so other function calls and through references can mutate, query, etc stable states properties
Borrows can't escape the with_borrow_mut closure for soundness reasons. (If it was possible, you could call it once, hold onto the borrow, and call it again -- resulting in a &mut T that aliases your escaped borrow. That would be instant UB.)
A staticMutex<_> or such might be an alternative to your thread local, but I didn't attempt it.
I was able to get something close by storing RefMuts inside MemoryRef and leaking one copy of State per thread.
Ideally, the thread local would be Rc<RefCell<…>> instead (which would solve the leaking problem), but I couldn’t find a good¹ way to create a smart pointer that does all of these things at the same time:
Keeps the Rc alive,
Holds the RefCell’s lock, and
Maps the locked value to something else
Âą i.e. Without dipping into writing my own unsafe code
Edit: Attempting the unsafe route…
I haven’t run anything through Miri, so I have pretty low confidence that this is actually correct, but I tried to write the unsafe version anyway. This is more of an exercise for myself than a suggestion— Please don’t actually use this without a lot of review from people that know this corner of Rust better than I do.
To facilitate such a review, here’s the relevant unsafe bits that I added:
trait Opaque {}
impl<T> Opaque for T {}
pub struct RcRefMut<T:'static> {
// NB: The 'static here is fake, and really points into `rc`!
// For safety, these fields MUST be in this order so that the drop sequence is correct.
ptr: RefMut<'static, T>,
rc: Rc<dyn Opaque>
}
impl<T> Deref for RcRefMut<T> {
type Target=T;
fn deref(&self)->&T { &self.ptr }
}
impl<T> DerefMut for RcRefMut<T> {
fn deref_mut(&mut self)->&mut T { &mut self.ptr }
}
impl<T> RcRefMut<T> {
pub fn map<U>(RcRefMut{ptr, rc}: Self, f:impl FnOnce(&mut T)->&mut U)->RcRefMut<U> {
RcRefMut {
ptr: RefMut::map(ptr, f),
rc
}
}
pub fn borrow_from(cell: &Rc<RefCell<T>>)->Self {
let rc = cell.clone();
let inner = Rc::as_ptr(cell);
let ptr = unsafe { (*inner).borrow_mut() };
RcRefMut { ptr, rc }
}
}