How does Rust allow calling a generic function with a trait object?

Hello there!
I was absolutely staggered to find out that this is valid code:

trait SomeTrait {}

fn by_trait_obj(st: &dyn SomeTrait) {
    by_generic(st);
}

fn by_generic<T: SomeTrait + ?Sized>(st: &T) {

}

How on earth does the Rust compiler know which T is by_generic going to be called with?

Is the function monophormized with every possible &T such that T: SomeTrait?

dyn Trait implements Trait itself, it's that simple.

2 Likes

It doesn't. The very point of dyn Trait is that it uses dynamic dispatch and a vtable to "remember" which concrete function it needs to forward to.

Here's a different way to say the same thing. Maybe it will be helpful.

dyn SomeTrait is itself a type, so the compiler generates a monomorphized version of by_generic for dyn SomeTrait, which will forward all calls through the vtable.

4 Likes

Thank you! That's what I was missing. I thought I could get something like this to work:

use std::any::TypeId;

trait MyTrait: 'static {}

struct MyStruct;

impl MyTrait for MyStruct {}

fn get_type_id<T: MyTrait + ?Sized>(_: &T) -> TypeId {
    TypeId::of::<T>()
}

fn main() {
    assert_eq!(
        get_type_id(&MyStruct),
        get_type_id(&MyStruct as &dyn MyTrait),
    );
}

But I was clearly missing the fact that dyn MyTrait is its own type.

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.