When you write a generic trait implementation such as
impl<'a, 'b, Iterable, Item> Scan for Iterable
it is required that all the generic types appear in the definition of the type that implements the trait. In your case Iterable
is there but Item
is not.
But you do not really need Item
to be generic. I think you are adding it just to write a constraint on it. Ideally you want to write something like:
impl<'a, 'b, Iterable> Scan for Iterable
where
&'b Iterable: IntoIterator<Item : Scan + 'a>,
Unfortunately that is still an unstable feature associated_type_bounds
.
But fortunately you do not need an associated type bound for that. You can write instead:
impl<'a, 'b, Iterable> Scan for Iterable
where
&'b Iterable: IntoIterator,
<&'b Iterable as IntoIterator>::Item : Scan + 'a,
Now the constraints work but the lifetimes fail!
error[E0309]: the parameter type `Iterable` may not live long enough
--> src/lib.rs:27:19
|
27 | &'b Iterable: IntoIterator,
| ^^^^^^^^^^^^ ...so that the reference type `&'b Iterable` does not outlive the data it points at
|
help: consider adding an explicit lifetime bound...
|
23 | impl<'a, 'b, Iterable: 'b> Scan for Iterable
| ++++
If you do as the compiler nicely suggests and add Iterable: 'b
and... now if fails in the implementation of the function itself:
error: lifetime may not live long enough
--> src/lib.rs:31:21
|
23 | impl<'a, 'b, Iterable> Scan for Iterable
| -- lifetime `'b` defined here
...
29 | fn scan(&self, arena: &mut Arena)
| - let's call the lifetime of this reference `'1`
30 | {
31 | for item in (&self).into_iter() {
| ^^^^^^^^^^^^^^^^^^^ argument requires that `'1` must outlive `'b`
Which is actually expected, as the anonymous lifetime of &self
is unrelated to 'b
, and you cannot change that because you cannot add constraints to the implementation of a function trait.
The obvious solution for this (without having any other code around, maybe it won't work for you) is to implement the trait for &'b Iterable
. This way &self
is actually &&'b Iterable
and all fits together. Moreover, now Iterable: 'b
is implicit and not needed anymore:
impl<'a, 'b, Iterable> Scan for &'b Iterable
where
&'b Iterable: IntoIterator,
<&'b Iterable as IntoIterator>::Item : Scan + 'a,
{
fn scan(&self, arena: &mut Arena)
{
for item in self.into_iter() {
item.scan(arena);
}
}
}
BTW, as it is I think the 'a
lifetime is mostly useless.