Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I derive a trait for another trait?

Tags:

rust

traits

I have a struct that holds a trait object member like this:

trait Contract {}

#[derive(Debug)]
struct Foo {
    x: Box<Contract>,
}

I want that struct to derive Debug, but the compiler doesn't like it:

error[E0277]: `Contract + 'static` doesn't implement `std::fmt::Debug`
 --> src/main.rs:5:5
  |
5 |     x: Box<Contract>,
  |     ^^^^^^^^^^^^^^^^ `Contract + 'static` cannot be formatted using `:?`; add `#[derive(Debug)]` or manually implement `std::fmt::Debug`
  |
  = help: the trait `std::fmt::Debug` is not implemented for `Contract + 'static`
  = note: required because of the requirements on the impl of `std::fmt::Debug` for `std::boxed::Box<Contract + 'static>`
  = note: required because of the requirements on the impl of `std::fmt::Debug` for `&std::boxed::Box<Contract + 'static>`
  = note: required for the cast to the object type `std::fmt::Debug`

I'm not really sure how to approach fixing this. I understand why the compiler can't implement Debug for the trait since it can't tell what types will implement it, but that same reason is what keeps me from implementing it manually for the trait (not even sure if that's even possible).

What would be a good approach to obtain the behaviour I want?

like image 227
Dash83 Avatar asked Apr 26 '18 10:04

Dash83


People also ask

What is a Rust trait?

A trait in Rust is a group of methods that are defined for a particular type. Traits are an abstract definition of shared behavior amongst different types. So, in a way, traits are to Rust what interfaces are to Java or abstract classes are to C++. A trait method is able to access other methods within that trait.

What is derive Rust?

The derive attribute allows new items to be automatically generated for data structures. It uses the MetaListPaths syntax to specify a list of traits to implement or paths to derive macros to process.

What is #[ derive debug )] in Rust?

#[...] is an attribute on struct Person . derive(Debug) asks the compiler to auto-generate a suitable implementation of the Debug trait, which provides the result of {:?} in something like format!(


1 Answers

Traits can't use the #[derive()] attribute; you need to implement it manually:

trait Contract {}

impl std::fmt::Debug for Contract {
    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
        write!(f, "{}", "derp")
    }
}

Since trait objects lose information on the type (type erasure) you could utilize the functions implemented by Contract, but you won't have access to the underlying types or their specific implementations of Debug.

If, however, you make Contract dependent on the Debug trait, ensuring that all its implementors must also implement Debug:

trait Contract: std::fmt::Debug {}

You will be able to #[derive(Debug)] for foo without having to implement Debug for Contract manually.

like image 77
ljedrz Avatar answered Oct 22 '22 02:10

ljedrz