Why am I unable to pass object of trait T where function expect X where T extends X?

I have the following kind of traits.

trait HasMeta {}
trait Expression: HasMeta + Debug {}

I have a function like below.

pub fn format_option_box(value: &Option<Box<dyn HasMeta>>, script: &str) -> String {

When I invoke that with an object of Expression then why does the compiler complain?

error[E0308]: mismatched types
   --> src/parser/ast.rs:344:59
344 |                 .add_fields("argument", format_option_box(argument, script))
    |                                                           ^^^^^^^^ expected trait `HasMeta`, found trait `Expression`
    = note: expected reference `&Option<Box<(dyn HasMeta + 'static)>>`
               found reference `&Option<Box<(dyn Expression + 'static)>>`

All Expression objects are guaranteed to implement HasMeta too then why does the compiler complain?

Because there's no inheritance in Rust, and every trait object has its own vtable which is unique to that trait and incompatible with others.

You have to add a method in your Expression that returns &dyn HasMeta or Box<dyn HasMeta>, and implement it explicitly.

BTW, avoid &Option<T>, and always prefer Option<&T> in arguments, because the first can be converted to the second, but not the other way.

Option<&dyn HasMeta>

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.