Yeah, this isn't going to work.
callback.borrow().as_ref().unwrap().as_ref().unchecked_ref()
Let's break this down in steps:
- You're borrowing
&RefCell<Option<Closure<FnMut()>>>
- so you now have Ref<Option<...>>
, which is step #1 of your issues. When this happens, this intermediary value now has a different lifetime than 'a
(inferior, to be precise). Anything stemming from this will inherit this lesser lifetime. Call it 'b
for now
- You then
as_ref
this Ref
, turning it into Option<&'b Closure<FnMut()>>
- Rust then converts
&'b Closure<FnMut()>
into &'b Function
Step 1 is where the snafu happens. Due to the lifetime clash, you're left with this mess. A semi-decent way to solve it the following construct:
use std::rc::{Rc};
use std::cell::{RefCell, Ref};
use std::ops::Deref;
struct CC<'a, T> {
inner: &'a Rc<RefCell<T>>,
borrow: Ref<'a, T>
}
impl<'a, T> CC<'a, T> {
pub fn from_callback(item:&'a Rc<RefCell<T>>) -> CC<'a, T> {
CC {
inner: item,
borrow: item.borrow()
}
}
pub fn to_function(&'a self) -> &'a T {
self.borrow.deref()
}
}
It's a bit unwieldy, but it's probably the cleanest way to do so.
A new struct
CC
is defined, containing a 'a
ref to Rc<RefCell<T>>
(where the T
generic in your case would end up being Option<Closure<FnMut()>>
) and a Ref
to T
with lifetime 'a
, auto-populated on the from_callback
constructor.
The moment you generate this object, you'll have a Ref
with the same lifetime as the ref you gave as an argument, making the entire issue go away. From there, you can call to_function
to retrieve a &'a
reference to your inner type.
There is a gotcha to this: as long as a single of these objects exists, you will (obviously) not be able to borrow_mut()
on the RefCell
, which may or may not kill your use case (as one doesn't use a RefCell
for the fun of it). Nevertheless, these objects are relatively cheap to instantiate, so you can afford to bin them once you're done with them.
An example with Function
and Closure
types replaced with u8
(because js_sys
cannot be imported into the sandbox) is available here.