Compile-time access to vtable


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?

1 Like


You can use this now on nightly

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 const inhabitable: Playground

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](

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:

1 Like


(It would be nice if mem::transmute were made a const fn itself…)

1 Like