Search code examples
rustiteratorflattenrust-clippy

How does flatten behave diffrently with Vec<Vec<_>> and Vec<Result<T<E>> or Vec<Option<T>> in rust


The official docs of iter::flatten states :

An iterator that flattens one level of nesting in an iterator of things that can be turned into iterators.

But for this code:

if let Ok(entries) = fs::read_dir("/path/to/dir") {
        for entry in entries {
            if let Ok(entry) = entry {
                // Do something
            }
        }
}

Clippy suggests to use entries.flatten() instead of if-let block, But here "nesting" is not there, instead it's an Iterator of Results. "Nesting" would look like an Iterator of Iterators.

There's no exclusive flatten() method implementation in ReadDir which is returned by fs::read_dir()

So my question is what exactly flatten do here? How does it work?


Solution

  • But here "nesting" is not there, instead it's an Iterator of Results

    Ah, but Result implements IntoIterator. This means you do effectively have nested iterators... or rather, nested items that can be turned into an iterator which is all the bound on Iterator::flatten() requires of an iterator's items:

    where Self::Item: IntoIterator
    

    The implementation for Result<T, E> yields the contained T when Ok and yields no items when Err. Therefore, clippy is correct -- you can use Iterator::flatten to simplify this code.

    And the same is true for Option<T>. When converted to an iterator, it will yield the contained T when Some and no items when None.