Rust supports trait inheritance, as follows [...] B: A means that if some type T implements B, it also needs to implement all the methods in A.
Technically, that is not inheritance but requirement. It is a trait bound not entirely dissimilar to one you'd have in a function: it constraints the type on which B is implementable to only types on which A is already implemented.
With that change in wording, the second version is much easier to understand: it's a lifetime bound, meaning it constraints the type on which B is implementable to only types with 'static
lifetime, meaning if you're trying to implement B on a type, that must either have no lifetime at all, or have a 'static
lifetime (or the implementation must have a lifetime bound aka only work for some uses of the type).
You can see that if you try to implement the trait on a lifetime-generic structure:
struct A<'a>(&'a str);
trait Display: 'static {
fn print(&self);
}
impl <'a>Display for A<'a> {
fn print(&self) { todo!() }
}
will yield
error[E0478]: lifetime bound not satisfied
That is because 'a
can be anything, so implementing Display
for A<'a>
means it is also implemented for non-'static
instances, which is not valid.
By adding the relevant lifetime bound on the impl, and thus limiting the implementation to A<'static>
instances:
struct A<'a>(&'a str);
trait Display: 'static {
fn print(&self);
}
impl <'a: 'static>Display for A<'a> {
fn print(&self) { todo!() }
}
the requirements of the trait are satisfied, and the impl is valid (nb: the 'a
is not necessary here you can just impl ... for A<'static>
, I'm showing it for regularity).
And if your struct has no lifetime it works by default, because no lifetime ~ 'static
:
struct A(String);
trait Display: 'static {
fn print(&self);
}
impl Display for A {
fn print(&self) { todo!() }
}
trait B: A
just means "if you implement B, you must also implement A". For the user of the trait, this has similar effect to that of inheritance because they can requireB
and count on gettingA
as well. But an implementor of B experiences no inheritance, they have to also (and separately) implement A. In that light,Display: 'static
means that, as a user ofDisplay
, you can count that the type that implements it has a'static
lifetime bound, which means that it doesn't borrow non-static data. – Temper