← [ ABORT TO HUD ]
SEQ. 1
SEQ. 2
Trait Objects, vtable Layouts & Sealed Traits
Dynamic Dispatch vs Monomorphization
Rust provides two distinct dispatch mechanisms:
- Static Dispatch (
impl Trait/ Generics): The compiler emits a separate, specialized copy of the function for each concrete type. Zero runtime overhead, allows aggressive inlining, but increases binary size. - Dynamic Dispatch (
dyn Trait): Uses a fat pointer (16 bytes on 64-bit platforms): 8 bytes for the data pointer, and 8 bytes for the vtable pointer.
Vtable Memory Layout
┌────────────────────────────────────────┐
│ Fat Pointer (16B) │
├───────────────────┬────────────────────┤
│ *data (8B) │ *vtable (8B) │
└─────────┬─────────┴─────────┬──────────┘
│ │
▼ ▼
┌───────────┐ ┌───────────────────────┐
│ Heap/Stack│ │ destructor: drop_in_pl│
│ Struct │ │ size: 24 bytes │
│ Fields │ │ align: 8 bytes │
└───────────┘ │ method_0: fn ptr │
│ method_1: fn ptr │
└───────────────────────┘
The Sealed Trait Pattern
When building public sovereign SDKs and internal systems, you often want users to implement certain traits while strictly preventing downstream consumers from implementing internal core traits:
mod private {
pub trait Sealed {}
}
// Public trait, but can only be implemented by types that implement private::Sealed!
pub trait KernelDispatch: private::Sealed {
fn execute_on_gpu(&self);
}
// Our crate can implement it:
impl private::Sealed for CudaTensorCoreKernel {}
impl KernelDispatch for CudaTensorCoreKernel {
fn execute_on_gpu(&self) { /* ... */ }
}
⌨ HANDS-ON LABInspect Vtable Layout and Dynamic Dispatch Overhead
⭐ +150 XPInspect fat pointer vtable generation for dyn Trait and verify static monomorphization inlining with cargo asm.
1Check trait object fat pointer sizing and alignment.
2Disassemble static dispatch function to prove complete inline monomorphization.
OBJECTIVE 1 / 2 — type "hint" if stuck
SYNAPSE VERIFICATION
QUERY 1 // 1
What is the memory size of a 'dyn Trait' reference on a 64-bit architecture?
16 bytes (8 bytes data pointer + 8 bytes vtable pointer)
8 bytes (single pointer directly to the vtable)
32 bytes (including full type descriptor string)
4 bytes (compressed index into the runtime symbol table)