I am writing code to parse CLI arguments and am stuck on quite a common Rust error.
What change (ideally without needing to assign everything to individual let variables, do I need to make to fix the compilation error?
I have been looking at a lot of similar posts as well as re-reaeding the chapter on Ownership in the rust book. However I haven't found a solution to my specific situation.
My code to parse the args is as follows:
The full file on github is here:
pub fn new<'a>(
args: env::Args,
default_world_def: Config<'static>,
presets: Vec<&'static str>,
) -> Result<Config<'a>, String> {
let args2 = args;
let args_vec = args2.collect::<Vec<String>>();
let args_slice = args_vec.as_slice();
let result = match args_slice {
[_, preset] => {
if preset == "help" {
Err(format!(
"try: gol
try: gol {:?}
try: gol [width height num_starting_cells seed display_dead display_alive] (e.g: gol 40 40 40 4045)",
presets
))
} else if presets.contains(&&preset[..]) {
Ok(Config::Preset {
key: preset.to_string(),
})
} else {
Err(format!("Unknown preset, choose from {:?}.", presets))
}
}
[_] => Ok(default_world_def),
[_, w, h, n, s] => {
let (width, height, num_starting_cells, seed) = Config::parse_args(&w, &h, &n, &s)?;
Ok(Config::WorldDef {
width,
height,
num_starting_cells,
seed,
dead_char: None,
alive_char: None,
})
}
[_, w, h, n, s, d, a] => {
let (width, height, num_starting_cells, seed) = Config::parse_args(&w, &h, &n, &s)?;
Ok(Config::WorldDef {
width,
height,
num_starting_cells,
seed,
dead_char: Some(&d),
alive_char: Some(&a),
})
}
args => Err(format!(
"Expected at least 4 or 6 args but got {}",
args.len() - 1
))
};
result
This results in the error:
error[E0515]: cannot return value referencing local variable `args_vec`
--> src/config.rs:77:9
|
27 | let args_slice = args_vec.as_slice();
| -------- `args_vec` is borrowed here
...
77 | result
| ^^^^^^ returns a value referencing data owned by the current function
I have tried:
- modifying lifetime parameters (making more things
static) - assigning the result of each method call to a variable (see
args2,args_vecandargs_sliceabove) - making the parameter
args: env::Argsto thenewfunction a reference (&)
As I understand the issue is that result references one/all of the args variables, which go out of scope and are dropped at the end of the new method which the result relies on in the future.