Type issue with Iterator collect

The type &(&str, &str) comes from what iter() on a Vec returns:

fn iter(&self) -> Iter<T>

where Iter<T> implements Iterator<Item=&T>:

impl<'a, T> Iterator for Iter<'a, T> {
    type Item = &'a T
    ...
}

In other words, iter() on a vector returns an iterator yielding references into the vector.

cloned() solves the problem because it is an iterator adapter which converts Iterator<Item=&T> to Iterator<Item=T> if T is cloneable. You can think of it as a shorthand for map(|v| v.clone()):

let v1: Vec<i32> = vec![1, 2, 3, 4];
let v2: Vec<_> = v1.iter().cloned().collect();
let v3: Vec<_> = v1.iter().map(|v| v.clone()).collect();
assert_eq!(v2, v3);

It happens that (&str, &str) is cloneable because each tuple component is also cloneable (all references are), so cloned() would return an object which implements Iterator<Item=(&str, &str)> – exactly what collect() needs to create a HashMap.

Alternatively, you can use into_iter() to get Iterator<Item=T> from Vec<T>, but then the original vector will be consumed:

use std::collections::HashMap;

fn main() {
    let pairs = vec!(("foo", "bar"), ("toto", "tata"));
    let map: HashMap<&str, &str> = pairs.into_iter().collect();
    println!("{:?}", map);
}

Leave a Comment

Hata!: SQLSTATE[HY000] [1045] Access denied for user 'divattrend_liink'@'localhost' (using password: YES)