Skip to content
This repository has been archived by the owner on Sep 12, 2024. It is now read-only.

Better compiler support for adding lifetime specifiers when returning iterators #54

Open
helanhalvan opened this issue Apr 19, 2023 · 0 comments

Comments

@helanhalvan
Copy link

Hi,

I'm not sure if this is the right forum, if not, I'm sorry. Anyway, I had some trouble with lifetime specifiers where the compile errors are a bit strange.

The original code looks like this:

pub fn pos_iter_to_cells(
    pos: impl IntoIterator<Item = Pos>,
    m: &Board,
) -> Vec<Option<(Pos, celldata::CellState)>> {
    let ret = pos
        .into_iter()
        .map(|p @ Pos { x, y }| match m.get(x) {
            Some(v) => match v.get(y) {
                None => None,
                Some(&a) => Some((p, a)),
            },
            None => None,
        })
        .collect();
    return ret;
}

The idea is to take an iterator of positions and return and iterator of positions and their contents, however I couldn't figure out what went wrong when returning an iterator. Just removing the collect and changing the return type leads to:

error[[E0700]](https://doc.rust-lang.org/stable/error_codes/E0700.html): hidden type for `impl IntoIterator<Item = Option<(Pos, CellState)>>` captures lifetime that does not appear in bounds

and recommends adding a lifetime specifier + '_, that addition in turn leads to this error:

error[[E0311]](https://doc.rust-lang.org/stable/error_codes/E0311.html): the associated type `<impl IntoIterator<Item = Pos> as IntoIterator>::IntoIter` may not live long enough

Now, the solution is to ensure pos and m live for at least as long as the return value, which is done by adding lifetime specifiers on the arguments and return value like this:

pub fn pos_iter_to_cells<'a>(
    pos: impl IntoIterator<Item = Pos> + 'a,
    m: &'a Board,
) -> impl IntoIterator<Item = Option<(Pos, CellState)>> + 'a {
    let ret = pos.into_iter().map(|p @ Pos { x, y }| match m.get(x) {
        Some(v) => match v.get(y) {
            None => None,
            Some(&a) => Some((p, a)),
        },
        None => None,
    });
    return ret;
}

However getting there for me required going and asking reddit. It might be that I missed some documentation, not sure. Anyway made a rust-lang-gist with all the types required. Here is the discussion on reddit

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant