0

I am trying to convert a Vec of a given struct to its String and eventually to &str format.

This example code simulates exactly what I am trying to achieve.

fn main() {
    let a = vec![1i32, 2i32, 3i32];

    let step1: Vec<String> = a.iter().map(|x| x.to_string()).collect::<Vec<String>>();

    let step2: Vec<&str> = step1.iter().map(AsRef::as_ref).collect::<Vec<&str>>();

    // This does not work as I was expecting it to
    // and its not being accepted by the compiler as valid code
    //
    let in_single_step: Vec<&str> = a
        .iter()
        .map(|x| x.to_string()) // <--- Something is needed after this step?
        .map(AsRef::as_ref)
        .collect::<Vec<&str>>();

    println!("{:?}", in_single_step);
}

playground with this code

I get an error:

error[E0631]: type mismatch in function arguments
  --> src/main.rs:14:10
   |
14 |         .map(AsRef::as_ref)
   |          ^^^
   |          |
   |          expected signature of `fn(std::string::String) -> _`
   |          found signature of `for<'r> fn(&'r _) -> _`

error[E0599]: no method named `collect` found for type `std::iter::Map<std::iter::Map<std::slice::Iter<'_, i32>, [closure@src/main.rs:13:14: 13:31]>, for<'r> fn(&'r _) -> &'r _ {<_ as std::convert::AsRef<_>>::as_ref}>` in the current scope
  --> src/main.rs:15:10
   |
15 |         .collect::<Vec<&str>>();
   |          ^^^^^^^
   |
   = note: the method `collect` exists but the following trait bounds were not satisfied:
           `&mut std::iter::Map<std::iter::Map<std::slice::Iter<'_, i32>, [closure@src/main.rs:13:14: 13:31]>, for<'r> fn(&'r _) -> &'r _ {<_ as std::convert::AsRef<_>>::as_ref}> : std::iter::Iterator`
           `std::iter::Map<std::iter::Map<std::slice::Iter<'_, i32>, [closure@src/main.rs:13:14: 13:31]>, for<'r> fn(&'r _) -> &'r _ {<_ as std::convert::AsRef<_>>::as_ref}> : std::iter::Iterator`

Similar questions are:

Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
ansrivas
  • 597
  • 2
  • 9
  • 14
  • You cannot create a `String` via `to_string()` then get a string slice to it. Nothing owns the `String` so it will be deallocated. – Shepmaster Sep 24 '19 at 15:07
  • So this can never be achieved in a single step and step1 -> step2 is the correct approach in this situation? – ansrivas Sep 24 '19 at 15:17
  • That is correct! The simpler case is `let x: &str = 1.to_string().as_ref(); println!("{}", x);` which also has a better error message. – Shepmaster Sep 24 '19 at 15:20
  • 1
    Your `Vec<&str>` is probably useless as you have to keep the `Vec` around and it can be used instead. – Denys Séguret Sep 24 '19 at 15:37
  • 1
    I think that some versions of @DenysSéguret's suggestion are [explained in code here](https://stackoverflow.com/a/33252901/155423) and [here](https://stackoverflow.com/a/41180422/155423) – Shepmaster Sep 24 '19 at 15:45

0 Answers0