This is for hobby/learning purposes. I’m trying to roll my own implementation of a Centered Interval Tree – I wanted to make a From<C>
for my IntervalTree
struct, where C
is some generic "iterable" collection.
In order to do that, I have two main steps:
- Do
for a in &coll
to compute the "center" - Do a
for a in coll
to consume the collection and build the tree
It seems like I need two type bounds for the C
:
C: IntoIterator<Item = A>,
&C: IntoIterator<Item = &A>
After following advice from the compiler, I’ve got lifetime bounds littered all over the place and have arrived at an error I don’t understand how to resolve:
fn iter_twice<'a, C: 'a, A: 'a>(coll: C)
where &'a C : IntoIterator<Item = &'a A>,
C: IntoIterator<Item = A>
{
for a in &coll {
// ...
}
for a in coll {
// ...
}
todo!()
}
error[E0597]: `coll` does not live long enough
--> src\itree.rs:57:14
|
53 | fn iter_twice<'a, C: 'a, A: 'a>(coll: C)
| -- lifetime `'a` defined here
...
57 | for a in &coll {
| ^^^^^
| |
| borrowed value does not live long enough
| argument requires that `coll` is borrowed for `'a`
...
66 | }
| - `coll` dropped here while still borrowed
I could make my life easier by just accepting Vec<A>
, but since this is "just for fun" I figured I’d try to make things work with type-generics.
>Solution :
Because you used a generic lifetime, the caller needs to choose it. But the lifetime the caller will choose does not necessarily match the lifetime of coll
(in fact, it can never match it), and this is the error.
What you want is Higher-Ranked Trait Bounds, meaning Iterator
is implemented for every lifetime:
fn iter_twice<C, A>(coll: C)
where
for<'a> &'a C: IntoIterator<Item = &'a A>,
C: IntoIterator<Item = A>,
{
// ...
}