Trait extension

If you want to use functions from another trait when implementing your own, you can require the other trait to be implemented for any type trying to implement yours. This can theoretically be seen as a form of inheritance, as by extending the already defined interface, you create a subtrait for the one you're requiring, therefore making that a supertrait.

You can also use a new trait to combine different traits together. This can be used to circumvent the limit of one non-auto trait for dyn types. This limit stems from the fact that each trait has its own virtual table when implemented on a type, and a dynamic type only has one virtual table pointer. The combined trait will have a virtual table that contains the function pointers of every supertrait.

Let us take a look at the head of the standard library error trait definition:

use std::fmt::{ Debug, Display };
pub trait Error: Debug + Display {
  ...
}

It requires both printing traits, meaning both have to be implemented by a type that implements the Error trait, but also that the functionality of both is available. A function receiving an error object will probably want to either print the error to a user if the user can fix it, or to some log (or inside a panic) otherwise. In the latter case, a programmer seeing the error or receiving a report will probably want the additional information provided by Debug printing, while a user could be confused by it and would prefer the more user-friendly Display version.