Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Rust convert iterator over String to &[&str]

How do I convert an iterator that returns Strings to something that I can pass into a function that takes &[&str]? I'm trying to map the iterator to an iterator over &strs, but I get an error:

error[E0515]: cannot return reference to function parameter `s`
  --> src/main.rs:89:52
   |
89 |     let args: Vec<&str> = std::env::args().map(|s| s.as_str()).collect();
   |                                                    ^^^^^^^^^^ returns a reference to data owned by the current function

Why does this error occur? args is a local variable in main so surely its lifetime extends to the end of the function and is therefore alive throughout the entire parse_args call.

If the function should take a different type I can change it, but I'm under the impression that this type is correct for my purposes - I don't need owned access to a vector, nor owned access to the values.

Here's the code that reproduces the error:

fn main() {
    let args: Vec<&str> = std::env::args().map(|s| s.as_str()).collect();
    let config = parse_args(&args);
    // do stuff with config
}


fn parse_args(args: &[&str]) {
// parse args
}
like image 991
The Bic Pen Avatar asked Dec 12 '25 16:12

The Bic Pen


1 Answers

You need to collect() twice, first into Vec<String> then iterate over that and collect() it into Vec<&str>:

let args: Vec<String> = std::env::args().collect();
let args: Vec<&str> = args.iter().map(|v| v.as_str()).collect();

let config = parse_args(&args);

This is because std::env::args() returns an iterator over Strings. If you convert them to &strs, they are dropped when we call the next item, and dang! your &str is dangling.

So we need somewhere to store the Strings, and then since we need &[&str] and not &[String], we need to iterate over this and collect it again.

Note however, that it is perfectly fine and normal to take &[String]. Unlike &String, which is basically useless - &str is always more flexible, this is not true behind an indirection, such as &[String] vs &[&str], precisely because of what we saw now.

If you want to be maximally permissive (for example, for a public function), you can take &[impl AsRef<str>]. This will allow both. Then when you use the data, you need to convert it to &str using as_ref().

like image 166
Chayim Friedman Avatar answered Dec 14 '25 12:12

Chayim Friedman