5
votes

I'm using getopts, and I was previously getting a value from a flag like this:

let file = matches.opt_str("f").unwrap();
let file_path = Path::new(&file);

But, I would like to handle the possible errors better, by making the path optional. This is my new code:

let file = matches.opt_str("f");
let file_path = match file {
    Some(f) => Some(Path::new(&f)),
    None    => None
}

But, when I try to compile this code, I get the error 'f' does not live long enough. I'm completely stumped.

Heres the MCVE of my code:

fn main() {
    let foo = Some("success".to_string());
    let string = match foo {
        Some(s) => Some(Path::new(&s)),
        None    => None
    };
}
1

1 Answers

6
votes

The issue arises because you are taking ownership of the contents of the Option in your match with the binding s (which uses bind-by-value). However, since nothing uses s after the match arm, it would be dropped and cause a invalid reference, so it's prevented.

Instead, you could bind-by-reference:

let string = match foo {
    Some(ref s) => Some(Path::new(s)),
    None        => None,
};

Or you could get an Option<&T> from the Option<T> using as_ref:

let string = match foo.as_ref() {
    Some(s) => Some(Path::new(s)),
    None    => None,
};

I'd probably use the last solution coupled with map:

let string = foo.as_ref().map(Path::new);