How to impl Trait<Box<dyn Any>> for a generic struct?

Hi community,

I have reduced my problem to the following MWE.

I would like to get rid of the redundant trait implementations for Dummy<i32> and Dummy<String>. I would prefer implementing Trait<Box<dyn Any>> for Dummy<U>, but I can't figure out how to do that.

Any hints are appreciated.

use std::any::{Any};

// Define a dummy struct
struct Dummy<U> { value: U }

// Define a generic trait
trait Trait<T> {
    fn set_value(&mut self, value: T);
}

// Trait for Dummy<i32>
impl Trait<Box<dyn Any>> for Dummy<i32> {
    fn set_value(&mut self, value: Box<dyn Any>) {
        if (&*value).type_id() == self.value.type_id() {
            self.value = *value.downcast().unwrap();
        } else {
            panic!("Cannot downcast.");
        }
        println!("{}", self.value);
    }
}

// Trait for Dummy<String>
impl Trait<Box<dyn Any>> for Dummy<String> {
    fn set_value(&mut self, value: Box<dyn Any>) {
        if (&*value).type_id() == self.value.type_id() {
            self.value = *value.downcast().unwrap();
        } else {
            panic!("Cannot downcast.");
        }
        println!("{}", self.value);
    }
}

fn main() {
    let mut dummy: Dummy<i32> = Dummy { value: 0 };
    dummy.set_value(Box::new(123 as i32));
    let mut dummy: Dummy<String> = Dummy { value: "".to_string() };
    dummy.set_value(Box::new("abc".to_string()));
}

You can implement the trait for any U that implements Any and Display

Playground

impl<U: Any + Display> Trait<Box<dyn Any>> for Dummy<U> {
    fn set_value(&mut self, value: Box<dyn Any>) {
        if (&*value).type_id() == self.value.type_id() {
            self.value = *value.downcast().unwrap();
        } else {
            panic!("Cannot downcast.");
        }
        println!("{}", self.value);
    }
}
1 Like

Hi semicoleon,

thank you for the solution. Is the following reasoning correct on why this is actually working? I'm trying to get my mental model regarding the rust trait/type system straight.

  • Restricting U to Any is necessary because of the if statement where type_id() is called, as this belongs to the Any trait
  • Restricting U to display is necessary because of the println
  • When using Dummy with an arbitrary U, the compiler will (a) check whether the type implements the necessary traits and (b) generate assembly for each variant of U it finds

Is that correct?

Yup, that's a good summary!