I'm having issues understanding the lifetime bound requirements when I use a trait in a type definition. For instance:
trait Kind { /* ... */ }
type CollectionOfKind<'a> = Vec<&'a Kind>;
// => error: explicit lifetime bound required
The requirement for lifetime bounds has already been discussed for the case of a trait within a struct (Answer 1, Answer 2). At first, I had problems to apply the approach of "adding the lifetime" here at all, since this does not work:
type CollectionOfKind<'a> = Vec<&'a Kind + 'a>;
type CollectionOfKind<'a> = Vec<&'a Kind + 'static>;
However, this was only a syntax issue, due to the precedence of plus as pointed out by @Shepmaster.
Overall, I now have found three ways to specify the lifetime bounds:
// Version 1: Adding 'static to the trait itself
trait Kind : 'static { /* ... */ }
type CollectionOfKind<'a> = Vec<&'a Kind>;
// Version 2: Adding 'static to the type definition
trait Kind { /* ... */ }
type CollectionOfKind<'a> = Vec<&'a (Kind + 'static)>;
// Version 3: Adding the lifetime of the reference to the trait object (?)
trait Kind { /* ... */ }
type CollectionOfKind<'a> = Vec<&'a (Kind + 'a)>;
What I don't understand: What is the exact difference between these three cases?
My problems:
In order to see the differences, I was trying to understand certain points mentioned in the other answers. For instance in the above linked Answer 2, I have found the following hint which I do not fully understand:
In this case, the
'static
requires that the underlying object must be a real struct, or a&'static
reference, but other references won't be allowed.
What does it mean that the underlying object must be a "real" struct? How is it possible for a struct to implement the trait without being "real"?
Similarly for the quote that @Shepmaster has cited:
You have to specify the lifetime two times: once for the lifetime of the reference, and once for the trait object itself, because traits can be implemented for references, and if the underlying object is a reference, you must specify its lifetime as well.
To be honest, I don't see why it must be specified twice. I though a trait object is defined by being a reference to an object which implements a certain trait. So it is by definition (?) a reference, and thus, has a lifetime anyways?
Answer for new question
You really have two orthogonal cases. I'll tackle the easier one first, the difference of #2 and #3. Comments are inline with what I hope is a representative example:
Of note here is that the lifetimes don't have to be the same! You could have written:
The second thing is the meaning of
trait Foo : 'static
. I'm less sure here, but I wrote this small example:This errors during compilation with
Based on that, I think that
Foo : 'static
is just another way of writingFoo + 'static
. The main difference I can think of is that it restricts the trait from ever being implemented on a struct with non-'static
lifetimes:Has the error
Original answer
I see you've found this out already, but you may want to update your version of Rust. If I compile your code on the Playpen, I get a suggestion on how to fix it:
That references RFC 438, Precedence of Plus.