3

I use to have extensive use of Vec<&str>, but someone on Discord talked me into changing that to &[&str], however in some cases this has produced problems. Take for example this code which used to work,

fn main() { 
  let pos: Vec<String> = vec!["foo".to_owned(), "bar".to_owned(), "baz".to_owned()];
  let pos: Vec<&str> = pos.iter().map(AsRef::as_ref).collect(); 
}

When I change that second line to

let pos: &[&str] = pos.iter().map(AsRef::as_ref).collect(); 

I get the error,

error[E0277]: a value of type `&[&str]` cannot be built from an iterator over elements of type `&_`
 --> bin/seq.rs:3:51
  |
3 |     let pos: &[&str] = pos.iter().map(AsRef::as_ref).collect();    
  |                                                      ^^^^^^^ value of type `&[&str]` cannot be built from `std::iter::Iterator<Item=&_>`
  |
  = help: the trait `FromIterator<&_>` is not implemented for `&[&str]`

How can I convert a Vec<String> into a &[&str]. I got this method from this answer on StackOverflow, which I tried to port to &[&str] with no luck.

Evan Carroll
  • 78,363
  • 46
  • 261
  • 468
  • Have you tried? `let pos:&[&str] = &pos.iter().map(AsRef::as_ref).collect::>()[..]` – Ömer Erden Oct 12 '21 at 06:22
  • you can trivially use a `&Vec` as a `&[T]`, there's a deref-coercion for it, but you need to `.collect()` into a `Vec`. – kmdreko Oct 12 '21 at 06:22
  • 1
    The advice you received sounds like it was either given or taken haphazardly, perhaps the reasoning was similar to this? [Why is it discouraged to accept a reference to a String (&String), Vec (&Vec), or Box (&Box) as a function argument?](https://stackoverflow.com/questions/40006219/why-is-it-discouraged-to-accept-a-reference-to-a-string-string-vec-vec-o) – kmdreko Oct 12 '21 at 06:27
  • @kmdreko If I try collecting into a vec and passing that in I get _the trait `From<&Vec<&str>>` is not implemented for `PositionalArgs<'_>`_ – Evan Carroll Oct 12 '21 at 06:36
  • Hello, it work in two time "let pos: Vec<&str> = pos.iter().map(AsRef::as_ref).collect();" and "let s: &[&str] = pos.as_slice();". But, perhaps a better solution exist – Zeppi Oct 12 '21 at 06:40
  • @Zeppi that works, just needed to convert the Vec to &[&str] with .as_slice(). If you want to answer I'll mark it as chosen. – Evan Carroll Oct 12 '21 at 06:47
  • @ÖmerErden just wanted to get back with you I filed this error on the diagnostics from your syntax (since I think that's also problematic) https://github.com/rust-lang/rust/issues/89805 – Evan Carroll Oct 12 '21 at 07:21
  • 1
    Please check the [as_slice](https://doc.rust-lang.org/std/vec/struct.Vec.html#method.as_slice), it does the same thing([playground](https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=be5a1ac8c976baa406db28968acc1a92)). And for the github issue, please be careful, that code is not correct, you are missing `&` while getting slice – Ömer Erden Oct 12 '21 at 07:22

1 Answers1

6

A simple way is to use .as_slice()

let pos: Vec<String> = vec!["foo".to_owned(), "bar".to_owned(), "baz".to_owned()];
let pos: Vec<&str> = pos.iter().map(AsRef::as_ref).collect();

let pos: &[&str] = pos.as_slice();

But, perhaps a better solution exist


Evan Carroll
  • 78,363
  • 46
  • 261
  • 468
Zeppi
  • 1,175
  • 6
  • 11
  • Great answer thanks a ton! If someone has a better answer, I'll accept it instead, but this is working for me. – Evan Carroll Oct 12 '21 at 06:53
  • Juste about the alternative proposition in github, "let pos: &[&str] = pos.iter().map(AsRef::as_ref).collect::>().as_slice();". This compile but not work. If you try to use pos it, i.e. "dbg!(pos)", get "error[E0716]: temporary value dropped while borrowed". – Zeppi Oct 12 '21 at 07:36