Trait object question

It seems that Rust checks trait object type differently when passing as reference? The following builds OK:


fn print_foo(value: Box<dyn MyTrait + Send>) {
    println!("{}", value.say());
}

fn main() {
    let f = Foo{};
    print_foo(Box::new(f));
}

but the following does not build:


fn print_foo(value: &Box<dyn MyTrait + Send>) {
    println!("{}", value.say());
}

fn main() {
    let f = Foo{};
    print_foo(&Box::new(f));
}

the error message is:

error[E0308]: mismatched types
  --> src/main.rs:20:15
   |
20 |     print_foo(&Box::new(f));
   |               ^^^^^^^^^^^^ expected trait object `dyn MyTrait`, found struct `Foo`
   |
   = note: expected reference `&Box<(dyn MyTrait + Send + 'static)>`
              found reference `&Box<Foo>`

Why did the build succeed when passing the value directly? Here is the full program in Playground.

If you explicitly cast the Box to a Box<dyn MyTrait + Send> it works:

fn main() {
    let f = Foo{};
    print_foo(&(Box::new(f) as Box<dyn MyTrait + Send>));
}

So it has to have something to do with how the compiler handles automatic promotion into trait objects.

(as an aside, if you want a reference to a trait object, it's better to accept &dyn MyTrait directly instead of &Box<dyn MyTrait> – the former can be used no matter what owns the trait object, whereas the latter forces the owner to use a Box.)

5 Likes

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.