0
votes

I'm trying to understand how trait objects are implemented in Rust. Please let me know if the following understanding is correct.

I have a function that takes any type that implements the Write trait:

fn some_func(write_to: &mut Write) {}

In any place where we have a type that implements this trait and calls the above function, the compiler generates a "trait object", probably by adding a call to TraitObject::new(data, vtable).

If we have something like:

let input = get_user_input(); // say we are expecting the input to be 1 or 2
let mut file = File::new("blah.txt").unwrap();
let mut vec: Vec<u8> = vec![1, 2, 3];

match input {
    1 => some_func(&mut file),
    2 => some_func(&mut vec),
}

will probably turn out to be:

match input {
    1 => {
        let file_write_trait_object: &mut Write =
            TraitObject::new(&file, &vtable_for_file_write_trait);
        some_func(file_write_trait_object);
    }
    2 => {
        let vec_write_trait_object: &mut Write =
            TraitObject::new(&vec, &vtable_for_vec_write_trait);
        some_func(vec_write_trait_object);
    }
}

Inside some_func the compiler will just access the methods used based on the vtable in the TraitObject passed along.

1
Have you read the documentation for TraitObject, which states: TraitObject is guaranteed to match layouts, but it is not the type of trait objects [...] nor does it control that layout [...]. It is only designed to be used by unsafe code that needs to manipulate the low-level details.Shepmaster
@Shepmaster: I wanted to understand if the above captures the "idea" of how compiler constructs a trait object and passes to the called function.user3169543

1 Answers

0
votes

Trait objects are fat pointers, so fn some_func(write_to: &mut Write) compiles to something like fn some_func(_: *mut OpaqueStruct, _: *const WriteVtable).