7

My goal is printing the contents of struct that has trait object member but I can't find how to tell Rust compiler that the member also implements other traits like Display or Debug.

For example, in the following program, I want to print the structure of S2 (and S1 for comparison) but I get stuck in the implementation of fmt.

trait Tr {}

impl Tr for usize {}

impl Tr for String {}

#[derive(Debug)]
struct S1<A: Tr + std::fmt::Debug> {
    member: Box<A>,
}

struct S2 {
    member: Box<Tr>,
}

impl std::fmt::Debug for S2 {
    fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> {
        // ??
        Ok(())
    }
}

fn main() {
    let s1 = S1 {
        member: Box::new(String::from("abc")),
    };

    println!("{:?}", s1);

    let s2 = S2 {
        member: Box::new(String::from("abc")),
    };

    println!("{:?}", s2);
}

My desired output of this program is

S1 { member: "abc" }
S2 { member: "abc" }

Is it possible to implement Debug for a struct like S2?

(Rust version: 1.35)

Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
letrec
  • 539
  • 5
  • 13
  • 1
    `T` is a bad name for a trait, because if I see `Box` I expect `T` to be a generic type parameter that has been provided via the struct, e.g. `struct S2 {}`. should be something longer – hellow May 28 '19 at 13:24

2 Answers2

5

Is it possible to implement Debug for a struct like S2?

Yes you can, and this is clearly pointed out in the Book

You need to implement the Debug trait for your S2 like following:

trait MyTrait {}
impl MyTrait for usize {}
impl MyTrait for String {}

trait MyTraitWritable: MyTrait + Debug {}
impl MyTraitWritable for usize {}
impl MyTraitWritable for String {}

impl std::fmt::Debug for S2 {
    fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> {
        write!(fmt, "S2 {{ member: {:?} }}", self.member)
    }
}

Playground

Akiner Alkan
  • 6,145
  • 3
  • 32
  • 68
1

You can make S2 generic but you don't need to specify that the type should also implement Debug right there. Instead, you can specify it in the impl:

struct S2<A: Tr> {
    member: Box<A>,
}

impl<A: Tr + std::fmt::Debug> std::fmt::Debug for S2<A> {
    fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> {
        write!(fmt, "S2 {{ member: {:?} }}", self.member)?;
        Ok(())
    }
}

This way, S2 will implement Debug if the actual type does.

Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
Gurwinder Singh
  • 38,557
  • 6
  • 51
  • 76