I'm reading the code of anyhow::Error and I liked that is using a raw vtable. However I'm trying to understand the reason. Couldn't this be implemented with just traits? What are the technical benefits of using a raw vtable instead of traits?
In general I noticed this pattern in other crates too, for example bytes::Bytes are using raw vtable. Or even std::task::Waker is using raw vtable.
I might be wrong but the two reasons I can think of for manual vtables are:
A dyn trait is a pointer to the vtable plus a pointer to the instance. If all you need is a pointer to the vtable there's no reason to carry two pointers around. Ditto if the instance pointer itself contains a pointer to the vtable (e.g. as the first member).
I believe the implementation of Rust's dyn trait is not guaranteed? A guaranteed layout is important for FFI, etc.