Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

How to accept a generic collection that works with both `for a in &coll` AND `for a in coll`

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:

  1. Do for a in &coll to compute the "center"
  2. 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:

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

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>,
{
    // ...
}
Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading