Please understand that your idea is not a bad idea in the abstract. The problem is only that it's not easily compatible with other design decisions already made in Rust. So many other things about Rust would have to change, to make this a feature that felt well-integrated, that it would effectively be a different language.
Hi, I have hitting that issue as well (especially when working on shakacode/messagebus). Here is how it may look like (al least on my opinion):
TraitObject has vtable for each type's impl - we can add typeid and next_sibling/prev_sibling to this vtable impl block. It will be possible to iterate through all dyn implementations for given type. And dynamic_cast function may look like (just draft):
pub unsafe fn dynamic_cast_ref<T: ?Sized + Unsized, U: ?Sized + Unsized>(tp: &T) -> Option<&U> {
let target = TypeId::of::<U>();
let to: TraitObject = mem::transmute(tp);
let mut v = to.vtable;
loop {
let td: Option<&DynDeclType> = mem::transmute(v.offset(NEXT_SIBLING_OFFSET));
let td = if let Some(val) = td {
val
} else {
break;
};
if td.type_id == target {
return Some(mem::transmute(TraitObject {data: to.data, vtable: td.vtable});
} else {
v = td.vtable;
}
}
// and same for prev_sibling as well
None
}
This would work if all code would be compiled at once. How would it work with rust's compulation model where each crate is compiled individually? We don't have control over the linker to add a way to implement next_sibling/prev_sibling across compilation units. Even if we could, that would require making all vtables exported, which would cause symbol conflicts due to the fact that vtables are copied once for every compilation unit that uses them.
Make sense. What about to add some optimization layer before linker (linker wrapper kind of)? It will allow access to compilation units and it will be possible to do necessary rust-related optimization before pass it to ld.
There is no guarantee that rustc is the one invoking the linker. With for example --crate-type staticlib or --emit obj, it is possible for an existing C build system to be the one invoking the linker.