I just discovered that Result FromIterator collection inversion nests to an arbitrary depth

45 points MaybeAStonedGuy

I wrote this little utility function for Advent of Code (given how many puzzles require parsing input line-by-line):

pub fn parse_items<I, O, E>(input: I) -> impl Iterator<Item = io::Result<Result<O, E>>>
where
    I: BufRead,
    O: FromStr<Err = E>,
{
    input.lines().filter_map(|line| {
        let line = match line {
            Ok(line) => line,
            Err(e) => return Some(Err(e)),
        };
        let line = line.trim();
        if line.is_empty() {
            None
        } else {
            Some(Ok(line.parse()))
        }
    })
}

And it turns out that this use of it is completely legal:

let numbers: io::Result<Result<Vec<Line>, Error>> = aoc::parse_items(input).collect();
let numbers = numbers??;

It makes sense, given the FromIterator impl:

impl<A, E, V> FromIterator<Result<A, E>> for Result<V, E> where
    V: FromIterator<A>,

Because Result<Vec<Line>> impls FromIterator<Result<Line>> and therefore io::Result<Result<Vec<Line>>> impls FromIterator<io::Result<Result<Line>>, but it's still kind of mind-bending to think about.