dyn Trait
- Rust course
- Advanced
- Lesson 54/81
- 4 min
Do dynamic dispatch with dyn Trait.
dyn Trait
A trait object (&dyn Ses, Box<dyn Ses>) is a fat pointer: a data address and a vtable address. The vtable is a compiler-generated table holding, for that concrete type, the addresses of the trait methods, the type's size, alignment and drop function:
use std::mem::size_of;
println!("{}", size_of::<&Kedi>()); // 8: a single pointer
println!("{}", size_of::<&dyn Ses>()); // 16: data + vtableThe call x.ses() reads the method's address from the vtable and jumps there: a single indirect call.
Why fat?
Since the concrete type isn't known at compile time, method addresses and the size are needed at runtime. Slices are fat pointers too (&[T] = address + length); types of unknown size like dyn Trait and [T] are called DSTs (dynamically sized types) and can only be used behind a pointer.
println!("{}", size_of::<&[u8]>()); // 16: address + length
println!("{}", size_of::<&str>()); // 16
// let x: dyn Ses; // error: size not knownPractice Pointer sizes
Write the Ses trait and the Kedi type. Print the values of size_of::<&Kedi>() and size_of::<&dyn Ses>() separated by a space (64-bit system).
Starter code
use std::mem::size_of;
fn main() {
// buraya yaz
}Sample solution
use std::mem::size_of;
trait Ses {
fn ses(&self) -> String;
}
struct Kedi;
impl Ses for Kedi {
fn ses(&self) -> String {
String::from("Miyav")
}
}
fn main() {
println!("{} {}", size_of::<&Kedi>(), size_of::<&dyn Ses>());
}Expected output
8 16
Questions and answers
Review the lesson questions together with their answers. To test yourself, solve the lesson interactively.
1 How many vtables are created for the same concrete type?
- One per object
- None
- They're built at runtime
- One per (type, trait) pair, shared by all objects Correct answer
Explanation: The vtable lives in static memory; a trait object only carries a pointer to it.
2 Trait object reference
let s: &____ Ses = &Kedi;
println!("{}", s.ses());
let s: &dyn Ses = &Kedi;
println!("{}", s.ses());
Explanation: &dyn Ses is a fat pointer to any type implementing Ses.
3 Type and size (64-bit)
| Term | Meaning |
|---|---|
&Kedi |
8 |
&dyn Ses |
16 |
&[u8] |
16 (address + length) |
Box<dyn Ses> |
16 (data + vtable) |