How to create a function which accepts multiple trait's objects?

In this case one trait extends the other. Below is a simplified code.

trait A {
    fn get_signature(&self) -> String;
}

trait B: A {
    fn something_else(&self);
}

fn are_same(x:&dyn A, y:&dyn A) -> bool {
    x.get_signature() == y.get_signature()
}

fn something_else_a(x:&dyn A, y:&dyn A) {
    if are_same(x, y) {
        // do something
    }
}

fn something_else_b(x:&dyn B, y:&dyn B) {
    if are_same(x as &dyn A, y) {
        // do something
    }
}

fn main() {
    
}

This code does not compile since I tried to pass B trait's object where A trait object is expected. My questions are why? After the APIs in A are guaranteed to be there in objects of B.

What alternative do I have other than copy pasting the complete are_same function as another function where input params are &dyn B?

You can add a helper method. And perhaps an additional trait, too, then you don’t need to implement the helper method yourself.

trait A {
    fn get_signature(&self) -> String;
}

trait AsDynA: A {
    fn as_dyn_a(&self) -> &dyn A;
}

impl<T: A> AsDynA for T {
    fn as_dyn_a(&self) -> &dyn A {
        self
    }
}

trait B: AsDynA {
    fn something_else(&self);
}

fn are_same(x: &dyn A, y: &dyn A) -> bool {
    x.get_signature() == y.get_signature()
}

fn something_else_a(x: &dyn A, y: &dyn A) {
    if are_same(x, y) {
        // do something
    }
}

fn something_else_b(x: &dyn B, y: &dyn B) {
    if are_same(x.as_dyn_a(), y.as_dyn_a()) {
        // do something
    }
}

fn main() {}


// no need to worry about AsDynA while implementing the traits if Self: Sized
struct SomeType;
impl A for SomeType {
    fn get_signature(&self) -> String {
        String::new()
    }
}
impl B for SomeType {
    fn something_else(&self) {}
}

Alternatively, making are_same generic could be an option. If this works for you, that’s probably the solution you’ll want over the other one, since it’s a bit simpler.

trait A {
    fn get_signature(&self) -> String;
}

trait B: A {
    fn something_else(&self);
}

fn are_same<T: A + ?Sized>(x: &T, y: &T) -> bool {
    x.get_signature() == y.get_signature()
}

fn something_else_a(x: &dyn A, y: &dyn A) {
    if are_same(x, y) {
        // do something
    }
}

fn something_else_b(x: &dyn B, y: &dyn B) {
    if are_same(x, y) {
        // do something
    }
}

fn main() {}

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.