This has nothing to do with arbitrary_self_type
, but DispatchFromDyn.
The problem is &Rc<dyn Trait>
currently is a thin pointer like &(Rc<()>, &VTable)
, not the regular DST representation like (&Rc<()>, &VTable)
. (There is no unsize-coercion relationship to &Rc<dyn Trait>
from &Rc<T>
.) So the compiler cannot generate the code for dynamic dispatch of &Rc<dyn Trait>
like the single-pointer counterpart:
fn dyn_dispatch_rc(self: Rc<dyn Trait>) {
let vtable = metadata(self);
(vtable.fptr_of_method)(self as Rc<()>)
// ^ just take the thin pointer part
}
However I don’t think we need to introduce this Borrow
type either. We just need to tell the compiler to obtain the vtable not from the pointer itself, but its pointee:
fn dyn_dispatch_rc_ref(self: &Rc<dyn Trait>) {
let vtable = metadata(*self); // ← take *self not self
(vtable.fptr_of_method)(self as &Rc<()>)
// object-slice the metadata part away
}
Meaning we should change the DispatchFromDyn
trait to require a method to extract the vtable
trait DispatchFromDyn<T> {
fn vtable(dst: &T) -> &'static VTable;
}
impl DispatchFromDyn<Rc<U>> for Rc<T> {
fn vtable(dst: &Rc<U>) -> &'static VTable {
metadata(*dst)
}
}
impl DispatchFromDyn<&Rc<U>> for &Rc<T> {
fn vtable(dst: &&Rc<U>) -> &'static VTable {
metadata(**dst)
}
}