The expression on the right side of the = constructs a Rc<RefCell<Box<dyn FnMut...>>>. The dyn value is never moved out of its Box.
Then, that value is coerced to the declared type Rc<RefCell<dyn FnMut...>> with another layer of dyn, which is allowed because Box implements FnMut when its contents do.
(By the way, please post text quotes instead of screenshots. Screenshots can be unreadable to some users or in some viewing conditions, and text allows us to copy parts of your code for easier testing and discussion of it.)
However - this means that it does not “work” in the sense that the Box is still there
I guess me asking how to make it leave the Box to reduce the indirection would make the topic decay to this which suggested an inconvenient trait workaround - I suppose the situation is still the same and we can’t directly convert a Box to a Rc<RefCell>?
That’s right. The approach I would take, if possible, is to avoid the Box and create Rc<RefCell<dyn FnMut...>> right away. Remember that both Rc and RefCell have functions fn(&mut Self) -> &mut T, so you can use it like a Box until you actually need the sharing. If it helps, you can define a wrapper:
/// Construct this only with `Rc`s that haven't been cloned.
struct NotRcYet<T: ?Sized>(pub Rc<RefCell<T>>);
impl<T: ?Sized> AsMut<T> for NotRcYet<T> {
fn as_mut(&mut self) -> &mut T {
Rc::get_mut(&mut self.0).unwrap().get_mut()
}
}
Then, use NotRcYet as a type to mark the absence of sharing. This actually has one advantage over your original plan: it doesn't re-allocate in order to move out of the Box. It's not very ergonomic, though. (What it really wants to be is the unstable UniqueRc type, which actually implements DerefMut and CoerceUnsized.)