See what types are for your first case:
for i in &["foo".to_string()] { let () = i; // expected `&collections::string::String`, // found `()` }
That is, the type of your iteration variable &String is not on String , as your function wants. The same thing happens for your second case. The third case works:
for i in vec!["foo".to_string()] { let () = i; // expected `collections::string::String`, // found `()` }
We can see the implementation for IntoIter for arrays and for all 3 forms of Vec . Note that the implementation for Vec<T> consumes a vector, while for &Vec<T> should return an iterator over the links to the elements.
You cannot use an array so that the iterator always returns links.
Here is an example that uses AsRef , which should do what you want:
use std::iter::IntoIterator; fn iterate<I, S>(v: I) where I: IntoIterator<Item=S>, S: AsRef<str> {} fn main() { iterate(&["foo"]); iterate(&["foo".to_string()]); iterate(["foo".to_string()].iter()); iterate(vec!["foo".to_string()]); iterate(&vec!["foo".to_string()]); }
This suggests that we are expecting a specific type that implements the Iterator trait. This iterator should AsRef<str> type that implements the AsRef<str> trait, allowing us to pass {arrays, vectors, slices} from { String , &str }.
source share