Type derivation in Rust

#1

Hello everyone,

I am trying to collect a iterator of iterators into a vector of iterators. As the name of the composite type is quite long, I tried to simplify it using generics:

// impl<I: Iterator> 
let iters = filenames.iter().map(|filename| {
    let fpath = format!("{}//{}", dirname, filename);
    let file = File::open(&fpath).expect("Fail to open file");
    let reader = BufReader::new(file);
    reader.lines().peekable()
}).collect::<Vec<Peekable<I>>>();

However, I ended up with an error:

a collection of type `std::vec::Vec<std::iter::Peekable<I>>` 
cannot be built from an iterator over elements of type 
`std::iter::Peekable<std::iter::Skip<std::io::Lines<std::io::BufReader<std::fs::File>>>>`

That is quite strange in my sense. Considering that std::io::Lines has implemented Iterator, why can’t the collection be built?

0 Likes

#2

Your code tries to collect to Peekable<I> but you have Peekable<Skip<Lines<...>>> instead, so the compiler rejects the obvious type mismatch. It’s unclear how your I type is related to this code, but your final value definitely doesn’t have any I in it, it’s a concrete type (as printed out by the compiler).

In this case, writing collect::<Vec<_>> will probably be enough.

1 Like

#3

Thanks for replying!

It’s in fact a typo (I simplified the snippet while forgot to update the output)

The original snippet looks like that:

// impl<I: Iterator> 
let iters = filenames.iter().map(|filename| {
    let fpath = format!("{}//{}", dirname, filename);
    let file = File::open(&fpath).expect("Fail to open file");
    let reader = BufReader::new(file);
    reader.lines().skip(1).peekable()
}).collect::<Vec<Peekable<I>>>();

And you are right, Vec<_> works like a charm.
But still, I am puzzled by the behaviour of the compiler – why does the compiler fail to derive the type even if I have provided a more detailed annotation?

Or more precisely, what the generic annotation should be so that it could match std::io::Lines? Like Iterator + Debug?

0 Likes

#4

To be generic for I: Iterator, your implementation must be able to work for any such I, but your code produces only that one particular type.

1 Like

#5

Thanks!

0 Likes