'What's the purpose of ".map(|&x| x)" in Rust

I'm learning Rust and noticed the following iterator pattern in a number of places:

let some_vector: &[& str] = &["hello", "world", "zombies", "pants"];
let result: Vec<&str> = some_vector
    .iter()
    .filter(|&x| *x == "hello")
    .map(|&x| x)
    .collect();

What's the purpose of that .map(|&x| x)? Why is it necessary? Does it create a copy?

When I remove it, I get the following compiler error:

error[E0277]: a value of type `Vec<&str>` cannot be built from an iterator over elements of type `&&str`
    --> src/main.rs:7:6
     |
7    |     .collect();
     |      ^^^^^^^ value of type `Vec<&str>` cannot be built from `std::iter::Iterator<Item=&&str>`
     |
     = help: the trait `FromIterator<&&str>` is not implemented for `Vec<&str>`
note: required by a bound in `collect`

For more information about this error, try `rustc --explain E0277`.

So the map turns an iterator over references to string slices into an iterator over string slices? Removing one level of indirection? Is that right?



Solution 1:[1]

Assuming you're using 2021 edition, it converts from impl Iterator< Item = &&str> to impl Iterator< Item = &str>:

let some_vector: &[& str] = &["hello", "world", "zombies", "pants"];
let result: Vec<&str> = some_vector // &[&str]
    .iter()                         // Iter<&str>
    .filter(|&x| *x == "hello")     // Impl Iterator< Item = &&str>
    .map(|&x| x)                    // Impl Iterator< Item = &str>
    .collect();

And the reason it's necessary is because the FromIterator trait is already implemented for &str as it's a relatively more common use case and it's not implemented for &&str as the error message says:

the trait `FromIterator<&&str>` is not implemented for `Vec<&str>`

Solution 2:[2]

In addition to @AlexW's answer, actually there is no need to write that, because there is a builtin iterator adapter that does it better (more clear, more performant): copied().

let some_vector: &[&str] = &["hello", "world", "zombies", "pants"];
let result: Vec<&str> = some_vector
    .iter()
    .filter(|&x| *x == "hello")
    .copied()
    .collect();

There is also cloned() which is equal to .map(|x| x.clone()).

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Alex W
Solution 2 Chayim Friedman