Transmuting the fat pointer of a trait object gives access its individual parts: the data pointer and the vtable pointer. The actual vtable itself, however, is a compile-time constant. I need to perform some checks and processing on the vtables during compilation or as a post-processing step. Is there a way to obtain the vtable address during compilation or from the resulting elf file? The best I could come up with thus far is generating the assembly output in which you can locate the vtables (rustfilt really helps with this), but I hope there is a more direct method.
Note that the layout of trait objects is not guaranteed so this transmute is likely UB.
There is a Pointer metadata & VTable RFC, which might eventually help?
You can use this now on nightly
https://doc.rust-lang.org/nightly/std/raw/struct.TraitObject.html
TraitObject
is guaranteed to have the same representation as a trait object. You’ll still have to transmute, but this time it will be sound. There is currently no way to do this on stable.
I know, thanks. However, I'm actually not interested in the layout of the trait object itself, but in the vtable address. I would prefer to process this at compile time, the trait objects do not even exist then. The transmute (eventhough being UB) will only work at run-time.
Thank you, I was pretty sure I did find something that was not UB for this transmute, but I could not find it anymore. However, this still only works at run-time when the trait objects are actually created in memory.
(Note that there is PIE, so it's more like a symbol accessible at link-time)
Here is something I have hacked my way to, which allows to get a specific type's vtable
, but requiring that as such type be : Playgroundconst
inhabitable
EDIT: Using *const dyn Trait
instead of &'static dyn Trait
gets rid of the const
-inhabitable requirement, as pointed out by @oli-obk
/*
trait Trait { ... }
struct Double;
impl Trait for Double { ... }
*/
const DOUBLE_AS_DYN_TRAIT_VTABLE: *mut () = unsafe {
const_transmute!([*const dyn Trait => raw::TraitObject](
ptr::null::<Double>()
)).vtable
};
I seem to get two different vtable addresses though, but with the same contents (checked with a debugger)
Note that there is no need to use an actual object, you can get a vtable by starting out with a raw pointer:
(It would be nice if mem::transmute
were made a const fn
itself…)
This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.