Better compiler support for adding lifetime specifiers when returning iterators #54
Description
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