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 shorten the lifetime of each item in IntoIterator?

The following is the code:

struct A;

fn f<'a, I>(default_args: I)
where
    I: IntoIterator<Item = &'a A>,
{
    {
        let a1 = A;
        let more_args = [&a1];
        {
            let i = default_args.into_iter();
            let i = i.chain(more_args);
            // I will use `i` here.
        }
    }
    // I will NOT use `*_args` here.
}

The following is error:

error[E0597]: `a1` does not live long enough
  --> src\main.rs:27:26
   |
21 | fn f<'a, I>(default_args: I)
   |      -- lifetime `'a` defined here
...
27 |         let more_args = [&a1];
   |                          ^^^ borrowed value does not live long enough
...
30 |             let i = i.chain(more_args);
   |                     ------------------ argument requires that `a1` is borrowed for `'a`
...
33 |     }
   |     - `a1` dropped here while still borrowed

For more information about this error, try `rustc --explain E0597`.

I want to get a new default_args_2 from default_args, where the Item inside default_args_2 has a shorter lifetime, as long as it valid inside the function.

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

>Solution :

You can add a little (almost) noop .map(|v| v):

let i = default_args.into_iter().map(|v| v);

The problem was that the iterator item types have to match, and therefore the chained iterator has to also yield &'a T, which it does not (it yields a shorter lifetime).

Since you don’t really need to use the items for 'a, the trick of the noop map() is to insert a subtyping point: Now, the closure inside map() (conceptually) converts the &'a T, to a &'shorter_lifetime T, which is fine since 'a: 'shorter_lifetime, but now the chained iterator can produce the desired item type.

Putting it differently, you cannot convert impl Iterator<Item = &'a T> into impl Iterator<Item = &'shorter_lifetime T> (as it may not be covariant over the lifetime), but you can convert &'a T to &'shorter_lifetime T, and we use that fact because from the outside we have impl Iterator<Item = &'a T>, but inside map()‘s closure we got &'a T.

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