CodeBlanks Logo Icon CodeBlanks

dyn Trait

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 + vtable

The 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 known

Practice 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

main.rs
use std::mem::size_of;

fn main() {
    // buraya yaz
}

Sample solution

main.rs
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

Question
let s: &____ Ses = &Kedi;
println!("{}", s.ses());
Answer
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)

All lessons in Advanced